home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / joe014.zip / JOE014.TAZ / JOE014.tar / joe.c < prev    next >
C/C++ Source or Header  |  1992-01-23  |  69KB  |  4,411 lines

  1. /* JOE - Joe's Own Editor - the bulk of the code is here
  2.    Copyright (C) 1991 Joseph H. Allen
  3.  
  4. This file is part of JOE (Joe's Own Editor)
  5.  
  6. JOE is free software; you can redistribute it and/or modify it under the terms
  7. of the GNU General Public License as published by the Free Software
  8. Foundation; either version
  9.  1, or (at your option) any later version.  
  10.  
  11. JOE is distributed in the hope that it will be useful, but WITHOUT ANY
  12. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  13. A PARTICULAR PURPOSE.  See the GNU General Public License for more details.  
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with JOE; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include <errno.h>
  24. #include <pwd.h>
  25. /* #include <sys/dir.h> */
  26. extern errno;
  27. #include "async.h"
  28. #include "blocks.h"
  29. #include "joe.h"
  30. int width=80;
  31. int height=24;
  32. int scroll=1;
  33. int noupdate=0;
  34. int repeatamnt=1;
  35. int nrepeatamnt;
  36.  
  37. unsigned char stalin[PATHSIZE];
  38.  
  39. int smode=0;
  40. int tops=0;
  41. int bots;
  42. int oxpos=0;            /* Current cursor position */
  43. int oypos=0;
  44. int *scrn;            /* Screen buffer address */
  45. unsigned char *help=0;
  46. int helplines=0;
  47. int helpsize=0;
  48. int helpblksize=0;
  49.  
  50. unsigned char *omsg=0;           /* Pointer to opening message */
  51.  
  52. dopen()
  53. {
  54. int x;
  55. unsigned char buf[30];
  56. scrn=(int *)malloc(width*height*sizeof(int));
  57. for(x=0;x<width*height;x++) scrn[x]= ' ';
  58. if(scroll)
  59.  {
  60.  sprintf(buf,"\033[0m\033[1;%dr\033[H\033[J",height), eputs(buf);
  61.  bots=height-1;
  62.  }
  63. else eputs("\033[0m\033[H\033[J");
  64. }
  65.  
  66. dclose()
  67. {
  68. setregn(0,height-1);
  69. cpos(height-1,0);
  70. attrib(0);
  71. }
  72.  
  73. resize()
  74. {
  75. int x;
  76. unsigned char buf[30];
  77. free(scrn);
  78. scrn=(int *)malloc(width*height*sizeof(int));
  79. for(x=0;x<width*height;x++) scrn[x]= ' ';
  80. if(scroll)
  81.  {
  82.  sprintf(buf,"\033[0m\033[1;%dr\033[H\033[J",height), eputs(buf);
  83.  bots=height-1;
  84.  }
  85. else eputs("\033[0m\033[H\033[J");
  86. smode=0;
  87. if(wind) wind=helplines;
  88. if(wind>height-3) wind=height-3;
  89. if(wind) hupd=1;
  90. wfit();
  91. upd=1;
  92. }
  93.  
  94. cposs(y,x)
  95. {
  96. unsigned char s[9];
  97. if(y>bots || y<tops) setregn(0,height-1);
  98. if(y==oypos)
  99.  {
  100.  if(x==oxpos) return;
  101.  if(x==0)
  102.   {
  103.   eputc(13);
  104.   return;
  105.   }
  106.  if(oxpos>=x+1 && oxpos<=x+4)
  107.   {
  108.   while(oxpos!=x) eputc(8), x++;
  109.   return;
  110.   }
  111.  if(x>=oxpos+1 && x<=oxpos+4)
  112.   {
  113.   while(x!=oxpos) tputcc(scrn[oypos*width+oxpos++]);
  114.   return;
  115.   }
  116.  if(x>oxpos)
  117.   sprintf(s,"\033[%dC",x-oxpos);
  118.  else
  119.   sprintf(s,"\033[%dD",oxpos-x);
  120.  eputs(s);
  121.  return;
  122.  }
  123. if(x==oxpos)
  124.  {
  125.  if(y>=oypos+1 && y<=oypos+4)
  126.   {
  127.   while(y!=oypos) /* acheck(), */ eputc(10), oypos++;
  128.   return;
  129.   }
  130.  if(y==0 && x==0)
  131.   {
  132.   eputs("\033[H");
  133.   return;
  134.   }
  135.  if(y>oypos)
  136.   sprintf(s,"\033[%dB",y-oypos);
  137.  else
  138.   sprintf(s,"\033[%dA",oypos-y);
  139.  eputs(s);
  140.  return;
  141.  }
  142. if(x<3 && y>oypos && y<oypos+5)
  143.  {
  144.  while(oypos!=y) ++oypos, eputc('\012');
  145.  eputc('\015'); oxpos=0;
  146.  while(x!=oxpos) tputcc(scrn[oypos*width+oxpos++]);
  147.  return;
  148.  }
  149. if(x==0 && y==0)
  150.  {
  151.  eputs("\033[H");
  152.  return;
  153.  }
  154. if(x==0)
  155.  {
  156.  sprintf(s,"\033[%dH",y+1);
  157.  eputs(s);
  158.  return;
  159.  }
  160. sprintf(s,"\033[%d;%dH",y+1,x+1);
  161. eputs(s);
  162. return;
  163. }
  164.  
  165. cpos(y,x)
  166. {
  167. cposs(y,x);
  168. oxpos=x;
  169. oypos=y;
  170. }
  171.  
  172. setregn(top,bot)
  173. {
  174. unsigned char sst[16];
  175. if(top!=tops || bots!=bot)
  176.  {
  177.  tops=top;
  178.  bots=bot;
  179.  if(scroll)
  180.   {
  181.   oxpos=0;
  182.   oypos=0;
  183.   sprintf(sst,"\033[%d;%dr\033[H",top+1,bot+1);
  184.   /* I shouldn't need the \033[H, but so many vt100 emulators forget to home
  185.    * the cursor after a set scrolling region...
  186.    */
  187.   eputs(sst);
  188.   }
  189.  }
  190. }
  191.  
  192. attrib(x)
  193. {
  194. if(smode== -1) goto clr;
  195. if(!(x&INVERSE) && (smode&INVERSE)) goto clr;
  196. if(!(x&BLINK) && (smode&BLINK)) goto clr;
  197. if(!(x&UNDERLINE) && (smode&UNDERLINE)) goto clr;
  198. if(!(x&BOLD) && (smode&BOLD)) goto clr;
  199. goto ovr;
  200. clr:
  201. smode=0;
  202. eputs("\033[m");
  203. ovr:
  204. if(x&INVERSE && !(smode&INVERSE)) eputs("\033[7m");
  205. if(x&BLINK && !(smode&BLINK)) eputs("\033[5m");
  206. if(x&UNDERLINE && !(smode&UNDERLINE)) eputs("\033[4m");
  207. if(x&BOLD && !(smode&BOLD)) eputs("\033[1m");
  208. smode=x;
  209. }
  210.  
  211. int uuu=0;
  212. int cntr=0;
  213. int upd=1;
  214. int hupd=0;
  215. int newy=1;
  216. int helpon=0;
  217. int wind=0;
  218. int xpos=0;
  219. int ypos=0;
  220. TXTSIZ saddr=0;
  221. TXTSIZ xoffset=0;
  222.  
  223. /* Clear end of line if needed.  i is row number and j is column number */
  224.  
  225. clreolchk(i,j)
  226. TXTSIZ j;
  227. {
  228. int *k=scrn+i*width;
  229. int t, jj;
  230. if(j<xoffset) jj=0;
  231. else
  232.  if(j>=xoffset+width-1) return;
  233.  else jj=j-xoffset;
  234. for(t=width-1;t>=jj;--t) if(k[t]!=' ') goto ohoh;
  235. return;
  236. ohoh:
  237. if(t==jj)
  238.  {
  239.  cpos(i,jj);
  240.  tputcc(' ');
  241.  k[jj]=' ';
  242.  oxpos++;
  243.  return;
  244.  }
  245. while(t>=jj) k[t--]=' ';
  246. cpos(i,jj);
  247. attrib(0);
  248. eputs("\033[K");
  249. }
  250.  
  251. /* Change buffer character to displayable form */
  252.  
  253. showas(ch)
  254. {
  255. #ifdef NOHIGHBIT
  256. if(ch>=128)
  257.  {
  258.  ch&=127;
  259.  ch|=INVERSE;
  260.  }
  261. #endif
  262. if((ch&127)<32)
  263.  {
  264.  ch+='@';
  265.  ch|=UNDERLINE;
  266.  }
  267. if((ch&127)==127)
  268.  {
  269.  ch&=~127;
  270.  ch|='?'|UNDERLINE;
  271.  }
  272. return ch;
  273. }
  274.  
  275. int udline(i)
  276. {
  277. int q=i*width;
  278. TXTSIZ j;
  279. int t;
  280. int u;
  281. int ch;
  282. for(j=0;1;j++)
  283.  {
  284.  if(have) return -1;
  285.  if(fmeof())
  286.   {
  287.   clreolchk(i++,j);
  288.   j=0;
  289.   while(i<curwin->wind+curwin->height) clreolchk(i++,j);
  290.   return 1;
  291.   }
  292.  ch=fmgetc();
  293.  if(ch==NL)
  294.   {
  295.   clreolchk(i,j);
  296.   return 0;
  297.   }
  298.  if(ch==TAB)
  299.   {
  300.   ch=' ';
  301.   if(fmnote()-1>=markb && fmnote()<=marke && curbuf==markbuf) ch^=INVERSE;
  302.   t=i*width+j-xoffset;
  303.   do
  304.    {
  305.    if(j>=xoffset && j<xoffset+width-1)
  306.     {
  307.     u=scrn[t];
  308.     if(ch!=u || u==-1)
  309.      {
  310.      cpos(i,(int)(j-xoffset));
  311.      scrn[t]=ch;
  312.      tputcc(ch);
  313.      oxpos++;
  314.      }
  315.     }
  316.    t++;
  317.    j++;
  318.    } while(j&7);
  319.   j--;
  320.   }
  321.  else
  322.   {
  323.   ch=showas(ch);
  324.   if(fmnote()-1>=markb && fmnote()<=marke && curbuf==markbuf) ch^=INVERSE;
  325.   t=q+j-xoffset;
  326.   if(j>=xoffset && j<xoffset+width-1)
  327.    {
  328.    u=scrn[t];
  329.    if(ch!=u || u==-1)
  330.     {
  331.     cpos(i,(int)(j-xoffset));
  332.     scrn[t]=ch;
  333.     tputcc(ch);
  334.     oxpos++;
  335.     }
  336.    }
  337.   }
  338.  }
  339. }
  340.  
  341. int udscrn()
  342. {
  343. int i;
  344. int v;
  345. for(i=ypos;i<curwin->height+curwin->wind;i++)
  346.  if(v=udline(i)) break;
  347. if(v== -1) return 0;
  348. fmpoint(saddr);
  349. for(i=curwin->wind+1;i<ypos;i++)
  350.  if(udline(i)) return 0;
  351. return 1;
  352. }
  353.  
  354. dupdate1(fgf)
  355. {
  356. int y;
  357. TXTSIZ x;
  358. TXTSIZ sve=fmnote();
  359.  
  360. TXTSIZ sve1;
  361.  
  362. /* Status line */
  363. strcpy(stalin,"\\i");
  364. if(gfnam[0]) strcat(stalin,gfnam);
  365. else strcat(stalin,"(Unnamed)");
  366. if(changed) strcat(stalin," (Modified)");
  367. if(record) strcat(stalin," (Macro recording)");
  368. if(!helpon && strlen(stalin)+21<width+1)
  369.  {
  370.  int x=strlen(stalin);
  371.  while(x<width-20) stalin[x++]=' ';
  372.  stalin[x]=0;
  373.  strcat(stalin,"Hit Ctrl-K H for help");
  374.  }
  375. else
  376.  {
  377.  int x=strlen(stalin);
  378.  while(x<width+1) stalin[x++]=' ';
  379.  stalin[x]=0;
  380.  }
  381.  
  382. msgout(curwin->wind,stalin,0,1);
  383.  
  384. x=getcol();
  385. if(fmnrnl()) fmpoint(fmnote()+1);
  386. sve1=fmnote();
  387.  
  388. /* calculate what screen cursor position should be */
  389.  
  390. if(x>xoffset+width-2)
  391.  xpos=width-2, xoffset=x-width+2;
  392. else
  393.  if(x<xoffset)
  394.   xpos=0, xoffset=x;
  395.  else
  396.   xpos=x-xoffset;
  397.  
  398. /* calculate new y cursor position and point to beginning of screen */
  399.  
  400. if(newy)
  401.  {
  402.  if(fmnote()<=saddr)
  403.   {
  404.   ypos=curwin->wind+1;
  405.   saddr=fmnote();
  406.   }
  407.  else
  408.   {
  409.   /* is cursor within 24 lines of old beginning of screen */
  410.  
  411.   for(y=0;y!=curwin->height-2;y++)
  412.    {
  413.    if(fmnote()==saddr) goto over;
  414.    fmrgetc();
  415.    if(fmnrnl()) fmpoint(fmnote()+1);
  416.    }
  417.   if(cntr)
  418.    {
  419.    for(x=0;x<(curwin->height-1)/2;x++)
  420.     {
  421.     fmfnl();
  422.     y--;
  423.     fmgetc();
  424.     }
  425.    }
  426.   over:
  427.   cntr=0;
  428.   saddr=fmnote();
  429.   ypos=y+curwin->wind+1;
  430.   }
  431.  newy=0;
  432.  }
  433.  
  434. /* Now update screen */
  435. if(have)
  436.  { if(fgf) cpos(ypos,xpos); }
  437. else
  438.  {
  439.  fmpoint(sve1);
  440.  if(udscrn()) upd=0;
  441.  if(fgf) cpos(ypos,xpos);
  442.  }
  443. fmpoint(sve);
  444. }
  445.  
  446. dupdatehelp()
  447. {
  448. int att;
  449. int i,j,c;
  450. unsigned char *from=help;
  451. int *too=scrn;
  452. if(helplines>height-3) wind=height-3;
  453. else wind=helplines;
  454. for(i=0;i!=wind;++too, ++i)
  455.  {
  456.  j=0; att=0;
  457.  loop:
  458.  if(have) return;
  459.  if(j==width-1)
  460.   {
  461.   while(*from!='\n') ++from;
  462.   ++from;
  463.   continue;
  464.   }
  465.  if(*from=='\n')
  466.   {
  467.   hclreol:
  468.   ++from;
  469.   cpos(i,j);
  470.   eputs("\033[K");
  471.   while(j!=width-1) *too++ =' ', ++j;
  472.   continue;
  473.   }
  474.  if(*from=='\\')
  475.   {
  476.   ++from;
  477.   if(*from=='\n') goto hclreol;
  478.   if(*from=='u')
  479.    {
  480.    att^=UNDERLINE;
  481.    ++from;
  482.    goto loop;
  483.    }
  484.   if(*from=='i')
  485.    {
  486.    att^=INVERSE;
  487.    ++from;
  488.    goto loop;
  489.    }
  490.   }
  491.  c= *from++ | att;
  492.  if(c!= *too)
  493.   {
  494.   cpos(i,j);
  495.   tputcc(*too= c);
  496.   oxpos++;
  497.   }
  498.  ++too; ++j;
  499.  goto loop;
  500.  }
  501. hupd=0;
  502. }
  503.  
  504. int updall=0;
  505.  
  506. dupdate()
  507. {
  508. int xp,yp;
  509.  
  510. aflush();
  511. if(hupd) dupdatehelp();
  512. if(upd)
  513.  {
  514.  int total=height-wind;
  515.  struct window *x;
  516.  dupdate1(1);
  517.  stwin(curwin);
  518.  x=curwin;
  519.  curwin=topwin;
  520.  xp=xpos; yp=ypos;
  521.  do
  522.   {
  523.   if((curbuf==x->buffer || updall) && curwin!=x)
  524.    {
  525.    if(total<=0) break;
  526.    ldwin(curwin);
  527.    total-=curwin->height;
  528.    newy=1;
  529.    dupdate1(0);
  530.    stwin(curwin);
  531.    }
  532.   else if(curwin==x)
  533.    total-=curwin->height;
  534.   }
  535.   while(curwin=curwin->next,curwin!=topwin);
  536.  updall=0;
  537.  ldwin(x);
  538.  curwin=x;
  539.  cpos(ypos=yp,xpos=xp);
  540.  }
  541. }
  542.  
  543. invalidate(line)
  544. {
  545. int x;
  546. for(x=0;x<width;x++) scrn[width*line+x]= -1;
  547. }
  548.  
  549. tputcc(c)
  550. {
  551. attrib(c);
  552. eputc(c&255);
  553. }
  554.  
  555. int backup=0;
  556. FILE *handle;
  557. unsigned char gfnam[PATHSIZE];
  558.  
  559. TXTSIZ bufsiz;        /* Size of buffer */
  560. TXTPTR point;        /* The point */
  561. TXTPTR buffer;        /* The buffer */
  562. TXTPTR filend;        /* First character not in buffer */
  563. TXTPTR hole;        /* Beginning of hole */
  564. TXTPTR ehole;        /* First character not in hole */
  565. int changed=0;        /* Set when file has been changed */
  566. int nundorecs=0;
  567. struct undorec
  568.  {
  569.  struct undorec *next;
  570.  TXTSIZ size;
  571.  TXTSIZ where;
  572.  unsigned char *buffer;
  573.  }
  574.  *undorecs=0;
  575. struct undorec *undoptr=0;
  576. struct undorec *redorecs=0;
  577. int undoflag=1;
  578.  
  579. fmopen()
  580. {
  581. buffer=(unsigned char *)TXTMALLOC(bufsiz=HOLESIZE);
  582. point=buffer;
  583. hole=buffer;
  584. ehole=buffer+HOLESIZE;
  585. filend=ehole;
  586. changed=0;
  587. undorecs=0;
  588. nundorecs=0;
  589. redorecs=0;
  590. undoptr=0;
  591. }
  592.  
  593. fmexpand(amount)
  594. unsigned amount;
  595. {
  596. if(filend+amount-buffer>bufsiz)
  597.  {
  598.  unsigned char *old=buffer;
  599.  buffer=(TXTPTR)TXTREALLOC(buffer,bufsiz=(filend+amount+HOLESIZE-buffer));
  600.  point+=buffer-old;
  601.  filend+=buffer-old;
  602.  hole+=buffer-old;
  603.  ehole+=buffer-old;
  604.  }
  605. }
  606.  
  607. fmhole()
  608. {
  609. if(point==hole) return;
  610. if(point==ehole)
  611.  {
  612.  point=hole;
  613.  return;
  614.  }
  615. if(point<hole)
  616.  {
  617.  bmove(ehole-(hole-point),point,hole-point);
  618.  ehole-=(hole-point);
  619.  hole=point;
  620.  }
  621. else
  622.  {
  623.  bmove(hole,ehole,point-ehole);
  624.  hole+=point-ehole;
  625.  ehole=point;
  626.  point=hole;
  627.  }
  628. }
  629.  
  630. fmbig(size)
  631. TXTSIZ size;
  632. {
  633. if(size>fmholesize())
  634.  {
  635.  size+=HOLESIZE;
  636.  fmexpand(size);
  637.  bmove(ehole+size,ehole,filend-ehole);
  638.  ehole+=size;
  639.  filend+=size;
  640.  }
  641. }
  642.  
  643. int fmfnl()
  644. {
  645. while(((point==hole)?(point=ehole):point)!=filend)
  646.  if(*point==NL) return 1;
  647.  else point++;
  648. return 0;
  649. }
  650.  
  651. int fmrnl()
  652. {
  653. if(fmrc()==NL) return 1;
  654. while((point==ehole?point=hole:point)!=buffer)
  655.  if(*(--point)==NL) return 1;
  656. return 0;
  657. }
  658.  
  659. killredo()
  660. {
  661. struct undorec *u;
  662. while(redorecs)
  663.  {
  664.  u=redorecs->next;
  665.  if(redorecs->buffer) free(redorecs->buffer);
  666.  free(redorecs);
  667.  redorecs=u;
  668.  }
  669. }
  670.  
  671. killundo()
  672. {
  673. struct undorec *u;
  674. while(undorecs)
  675.  {
  676.  if(undorecs->buffer) free(undorecs->buffer);
  677.  u=undorecs->next;
  678.  free(undorecs);
  679.  undorecs=u;
  680.  }
  681. }
  682.  
  683. fminsu(size)
  684. TXTSIZ size;
  685. {
  686. struct window *z;
  687. struct undorec *it;
  688. if(undoflag)
  689.  {
  690.  if(redorecs) killredo();
  691.  if(undorecs && !undorecs->buffer &&
  692.     (undorecs->where==fmnote() || undorecs->where+undorecs->size==fmnote()))
  693.   undorecs->size+=size;
  694.  else
  695.   {
  696.   /* New record */
  697.   it=(struct undorec *)malloc(sizeof(struct undorec));
  698.   it->next=undorecs;
  699.   undorecs=it;
  700.   it->size=size;
  701.   it->where=fmnote();
  702.   it->buffer=0;
  703.   ++nundorecs;
  704.   if(nundorecs==20)
  705.    {
  706.    struct undorec *p;
  707.    for(it=undorecs;it->next;p=it,it=it->next);
  708.    if(it->buffer) free(it->buffer);
  709.    free(it);
  710.    p->next=0;
  711.    }
  712.   }
  713.  }
  714. if(curbuf==markbuf)
  715.  {
  716.  if(fmnote()<markb) markb+=size;
  717.  if(fmnote()<marke) marke+=size;
  718.  }
  719. z=topwin;
  720. do
  721.  {
  722.  if(z->buffer==curbuf)
  723.   {
  724.   if(z==curwin)
  725.    {
  726.    if(fmnote()<saddr) saddr+=size;
  727.    }
  728.   else
  729.    {
  730.    if(fmnote()<z->saddr) z->saddr+=size;
  731.    if(fmnote()<z->cursor) z->cursor+=size;
  732.    }
  733.   }
  734.  z=z->next;
  735.  }
  736.  while(z!=topwin);
  737. }
  738.  
  739. undo()
  740. {
  741. struct undorec *u;
  742. if(!undorecs) return;
  743. extend=0;
  744. if(!undoptr) undoptr=undorecs;
  745. if(fmnote()==undoptr->where)
  746.  {
  747.  if(undoptr->buffer)
  748.   {
  749.   undoflag=0;
  750.   fminss(undoptr->buffer,undoptr->size);
  751.   undoflag=1;
  752.   markbuf=curbuf;
  753.   markb=fmnote();
  754.   marke=markb+undoptr->size;
  755.   u=(struct undorec *)malloc(sizeof(struct undorec));
  756.   u->next=redorecs;
  757.   redorecs=u;
  758.   u->size=undoptr->size;
  759.   u->buffer=0;
  760.   u->where=fmnote();
  761.   }
  762.  else
  763.   {
  764.   u=(struct undorec *)malloc(sizeof(struct undorec));
  765.   u->next=redorecs;
  766.   redorecs=u;
  767.   u->size=undoptr->size;
  768.   u->buffer=(unsigned char *)malloc(undoptr->size);
  769.   fmcpy(u->buffer,undoptr->size);
  770.   u->where=fmnote();
  771.   undoflag=0;
  772.   fmdel(undoptr->size);
  773.   markb=marke=0;
  774.   undoflag=1;
  775.   }
  776.  u=undoptr->next;
  777.  if(undoptr->buffer) free(undoptr->buffer);
  778.  free(undoptr);
  779.  undoptr=undorecs=u;
  780.  }
  781. else fmpoint(undoptr->where), newy=1;
  782. }
  783.  
  784. redo()
  785. {
  786. struct undorec *u;
  787. if(!redorecs) return;
  788. extend=0;
  789. fmpoint(redorecs->where), newy=1;
  790. if(redorecs->buffer)
  791.  {
  792.  undoflag=0;
  793.  fminss(redorecs->buffer,redorecs->size);
  794.  undoflag=1;
  795.  markbuf=curbuf;
  796.  markb=fmnote();
  797.  marke=markb+redorecs->size;
  798.  u=(struct undorec *)malloc(sizeof(struct undorec));
  799.  u->next=undorecs;
  800.  undorecs=undoptr=u;
  801.  u->size=redorecs->size;
  802.  u->buffer=0;
  803.  u->where=fmnote();
  804.  }
  805. else
  806.  {
  807.  u=(struct undorec *)malloc(sizeof(struct undorec));
  808.  u->next=undorecs;
  809.  undorecs=undoptr=u;
  810.  u->size=redorecs->size;
  811.  u->buffer=(unsigned char *)malloc(redorecs->size);
  812.  fmcpy(u->buffer,redorecs->size);
  813.  u->where=fmnote();
  814.  undoflag=0;
  815.  fmdel(redorecs->size);
  816.  markb=marke=0;
  817.  undoflag=1;
  818.  }
  819. u=redorecs->next;
  820. if(redorecs->buffer) free(redorecs->buffer);
  821. free(redorecs);
  822. redorecs=u;
  823. }
  824.  
  825. fmdelu(size)
  826. TXTSIZ size;
  827. {
  828. struct window *z;
  829. struct undorec *it;
  830. if(undoflag)
  831.  {
  832.  if(redorecs) killredo();
  833.  if(undorecs && undorecs->buffer && (undorecs->where==fmnote()))
  834.   {
  835.   /* Add to end */
  836.   undorecs->buffer=(unsigned char *)realloc(undorecs->buffer,
  837.   undorecs->size+size);
  838.   fmcpy(undorecs->buffer+undorecs->size,size);
  839.   undorecs->size+=size;
  840.   }
  841.  else if(undorecs && undorecs->buffer && (undorecs->where==fmnote()+size))
  842.   {
  843.   /* Add to beginning */
  844.   undorecs->buffer=(unsigned char *)realloc(
  845.   undorecs->buffer,undorecs->size+size);
  846.   bbkwd(undorecs->buffer+size,undorecs->buffer,undorecs->size);
  847.   fmcpy(undorecs->buffer,size);
  848.   undorecs->size+=size;
  849.   undorecs->where-=size;
  850.   }
  851.  else
  852.   {
  853.   /* New record */
  854.   it=(struct undorec *)malloc(sizeof(struct undorec));
  855.   it->next=undorecs;
  856.   undorecs=it;
  857.   it->size=size;
  858.   it->where=fmnote();
  859.   it->buffer=(unsigned char *)malloc(size);
  860.   fmcpy(it->buffer,size);
  861.   ++nundorecs;
  862.   if(nundorecs==20)
  863.    {
  864.    struct undorec *p;
  865.    for(it=undorecs;it->next;p=it,it=it->next);
  866.    if(it->buffer) free(it->buffer);
  867.    free(it);
  868.    p->next=0;
  869.    }
  870.   }
  871.  }
  872. if(markbuf==curbuf)
  873.  {
  874.  if(fmnote()<markb) markb-=umin(size,markb-fmnote());
  875.  if(fmnote()<marke) marke-=umin(size,marke-fmnote());
  876.  }
  877. z=topwin;
  878. do
  879.  {
  880.  if(curbuf==z->buffer)
  881.   {
  882.   if(z==curwin)
  883.    {
  884.    if(fmnote()<saddr) saddr-=umin(size,saddr-fmnote());
  885.    }
  886.   else
  887.    {
  888.    if(fmnote()<z->saddr) z->saddr-=umin(size,z->saddr-fmnote());
  889.    if(fmnote()<z->cursor) z->cursor-=umin(size,z->cursor-fmnote());
  890.    }
  891.   }
  892.  z=z->next;
  893.  }
  894.  while(z!=topwin);
  895. }
  896.  
  897. fmdel(x)
  898. TXTSIZ x;
  899. {
  900. fmhole();
  901. fmdelu(x);
  902. ehole+=x;
  903. changed=1;
  904. }
  905.  
  906. fminss(string,size)
  907. unsigned char *string;
  908. unsigned size;
  909. {
  910. fminsu(size);
  911. fmhole();
  912. if(size>fmholesize()) fmbig(size);
  913. bmove(hole,string,size);
  914. hole+=size;
  915. changed=1;
  916. }
  917.  
  918. fmcpy(string,size)
  919. unsigned char *string;
  920. {
  921. fmhole();
  922. bbkwd(string,ehole,size);
  923. }
  924.  
  925. int fmcmp(string,size)
  926. unsigned char *string;
  927. int size;
  928. {
  929. unsigned char *x;
  930. if(point==hole) point=ehole;
  931. if(hole>point && hole<point+size && hole!=ehole)
  932.  {
  933.  if(fmcmp(string,hole-point)) return 1;
  934.  else
  935.   {
  936.   x=point;
  937.   point=ehole;
  938.   if(fmcmp(string+(hole-x),size-(hole-x)))
  939.    {
  940.    point=x;
  941.    return 1;
  942.    }
  943.   else
  944.    {
  945.    point=x;
  946.    return 0;
  947.    }
  948.   }
  949.  }
  950. else
  951.  {
  952.  x=point;
  953.  do
  954.   if(*(x++)!=*(string++)) return 1;
  955.   while(--size);
  956.  return 0;
  957.  }
  958. }
  959.  
  960. int tupp(c)
  961. unsigned char c;
  962. {
  963. if(c>='a' && c<='z') return c+'A'-'a';
  964. else return c;
  965. }
  966.  
  967. int fmicmp(string,size)
  968. unsigned char *string;
  969. int size;
  970. {
  971. unsigned char *x;
  972. if(point==hole) point=ehole;
  973. if(hole>point && hole<point+size && hole!=ehole)
  974.  {
  975.  if(fmcmp(string,hole-point)) return 1;
  976.  else
  977.   {
  978.   x=point;
  979.   point=ehole;
  980.   if(fmcmp(string+(hole-x),size-(hole-x)))
  981.    {
  982.    point=x;
  983.    return 1;
  984.    }
  985.   else
  986.    {
  987.    point=x;
  988.    return 0;
  989.    }
  990.   }
  991.  }
  992. else
  993.  {
  994.  x=point;
  995.  do
  996.   if(tupp(*(x++))!=tupp(*(string++))) return 1;
  997.   while(--size);
  998.  return 0;
  999.  }
  1000. }
  1001.  
  1002. int fmsave(file,size)
  1003. FILE *file;
  1004. TXTSIZ size;
  1005. {
  1006. if(!size) return 1;
  1007. if(point==hole) point=ehole;
  1008. if(hole>point && hole<point+size && hole!=ehole)
  1009.  {
  1010.  if(hole-point!=fwrite(point,1,hole-point,file)) return 0;
  1011.  if(size-(hole-point)!=fwrite(ehole,1,size-(hole-point),file)) return 0;
  1012.  return 1;
  1013.  }
  1014. else
  1015.  return size==fwrite(point,1,size,file);
  1016. }
  1017.  
  1018. int fminsfil(file)
  1019. FILE *file;
  1020. {
  1021. struct stat buf;
  1022. TXTSIZ amount;
  1023. fstat(fileno(file),&buf);
  1024. if(buf.st_size==0) return 1;
  1025. fminsu(buf.st_size);
  1026. changed=1;
  1027. fmhole();
  1028. fmbig(buf.st_size);
  1029. amount=fread(hole,1,buf.st_size,file);
  1030. hole+=amount;
  1031. return amount==buf.st_size;
  1032. }
  1033.  
  1034. /* Output a message string which might possibly longer than width */
  1035. /* if flg is set and the string is longer than the line, the cursor is
  1036.  * left at the last position on the line.  If it is clear, the cursor may be
  1037.  * elsewhere because of screen optimization. */
  1038. /* if flg1 is set, attribute escape sequences \i and \u are taken to mean
  1039.  * switch to inverse or switch to underline attributes
  1040.  */
  1041.  
  1042. msgout(row,str,flg,flg1)
  1043. unsigned char *str;
  1044. {
  1045. int j=0, c, att=0;
  1046. int *too=scrn+width*row;
  1047. loop:
  1048. if(j==width-1)
  1049.  {
  1050.  if(flg) cpos(row,j);
  1051.  return;
  1052.  }
  1053. if(!*str)
  1054.  {
  1055.  hclreol:
  1056.  cpos(row,j);
  1057.  eputs("\033[K");
  1058.  while(j!=width-1) *too++ =' ', ++j;
  1059.  return;
  1060.  }
  1061. if(*str=='\\' && flg1 && (str[1]=='i' || str[1]=='u'))
  1062.  {
  1063.  ++str;
  1064.  if(!*str) goto hclreol;
  1065.  if(*str=='u')
  1066.   {
  1067.   att^=UNDERLINE;
  1068.   ++str;
  1069.   goto loop;
  1070.   }
  1071.  if(*str=='i')
  1072.   {
  1073.   att^=INVERSE;
  1074.   ++str;
  1075.   goto loop;
  1076.   }
  1077.  }
  1078. c= showas(*str++) ^ att;
  1079. if(c!= *too)
  1080.  {
  1081.  cpos(row,j);
  1082.  tputcc(*too= c);
  1083.  oxpos++;
  1084.  }
  1085. ++too; ++j;
  1086. goto loop;
  1087. }
  1088.  
  1089. int getl(prompt,dat)
  1090. unsigned char *prompt;
  1091. unsigned char *dat;
  1092. {
  1093. int ch,x,y;
  1094. int flag=0;
  1095. unsigned char buf[PATHSIZE];
  1096. strcpy(buf,prompt);
  1097. strcat(buf," (^C to abort): ");
  1098. y=strlen(buf);
  1099. strcat(buf,dat);
  1100. x=strlen(buf);
  1101. while(1)
  1102.  {
  1103.  if(x>width-1) msgout(height-1,buf+x-(width-1),1,0);
  1104.  else msgout(height-1,buf,1,0);
  1105.  ch=anext();
  1106.  if(ch=='`' && !flag)
  1107.   {
  1108.   flag=1;
  1109.   continue;
  1110.   }
  1111.  if(ch>=32 && ch!=127 || flag)
  1112.   {
  1113.   if(flag && ch=='?') ch=127;
  1114.   else if(flag && ch!='`') ch&=0x1f;
  1115.   flag=0;
  1116.   buf[x+1]=0, dat[x+1-y]=0;
  1117.   buf[x]=ch, dat[x++-y]=ch;
  1118.   continue;
  1119.   }
  1120.  if(ch=='L'-'@')
  1121.   {
  1122.   ch= -1;
  1123.   break;
  1124.   }
  1125.  if(ch==13 || ch==10)
  1126.   {
  1127.   ch=1;
  1128.   break;
  1129.   }
  1130.  if((ch==8 || ch==127) && x-y)
  1131.   {
  1132.   x--;
  1133.   dat[x-y]=0;
  1134.   buf[x]=0;
  1135.   continue;
  1136.   }
  1137. /*
  1138.  if(ch==9)
  1139.   {
  1140.   dat[x-y]=0;
  1141.   docomplete(dat);
  1142.   strcpy(buf+y,dat);
  1143.   x=strlen(buf);
  1144.   continue;
  1145.   }
  1146. */
  1147.  if(ch==3)
  1148.   {
  1149.   ch=0;
  1150.   break;
  1151.   }
  1152.  }
  1153. return ch;
  1154. }
  1155.  
  1156. msg(ms)
  1157. unsigned char *ms;
  1158. {
  1159. msgout(height-1,ms,1,1);
  1160. anext();
  1161. }
  1162.  
  1163. int askyn(ms)
  1164. unsigned char *ms;
  1165. {
  1166. int ch;
  1167. msgout(height-1,ms,1,1);
  1168. up:
  1169. ch=anext();
  1170. switch(ch)
  1171.  {
  1172. case 'y':
  1173. case 'n':
  1174.  eputc(ch);
  1175.  ch&=0x5f;
  1176.  break;
  1177. case 'Y':
  1178. case 'N':
  1179.  eputc(ch);
  1180.  break;
  1181. case 3:
  1182.  ch= -1;
  1183.  break;
  1184. default:
  1185.  goto up;
  1186.  }
  1187. return ch;
  1188. }
  1189.  
  1190. int query(ms)
  1191. unsigned char *ms;
  1192. {
  1193. msgout(height-1,ms,1,1);
  1194. return anext();
  1195. }
  1196.  
  1197. int nquery(ms)
  1198. unsigned char *ms;
  1199. {
  1200. msgout(height-1,ms,1,1);
  1201. cpos(ypos,xpos);
  1202. return anext();
  1203. }
  1204.  
  1205. imsg()
  1206. {
  1207. attrib(0);
  1208. if(omsg) msgout(1,omsg,0,1);
  1209. upd=1;
  1210. msgout(height-1,"\\i** Joe's Own Editor version 0.1.4 (1991) **\\i",0,1);
  1211. cpos(1,0);
  1212. }
  1213.  
  1214. int pic;
  1215. int autoind;
  1216. int overwrite;
  1217. int wrap;
  1218. int tabmagic;
  1219. TXTSIZ rmargin;
  1220.  
  1221. int options=0;
  1222. unsigned char sstring[PATHSIZE];
  1223. unsigned char rstring[PATHSIZE];
  1224. int len;
  1225.  
  1226. TXTSIZ markb=0;
  1227. TXTSIZ marke=0;
  1228.  
  1229. TXTSIZ added;
  1230. TXTSIZ extend;
  1231. int leave;       /* set if editor should now exit */
  1232.  
  1233. TXTSIZ getrcol()
  1234. {
  1235. TXTSIZ x,y;
  1236. unsigned char ch;
  1237. x=fmnote();
  1238. if(fmnrnl()) fmgetc();
  1239. y=0;
  1240. while(fmnote()!=x)
  1241.  {
  1242.  ch=fmgetc();
  1243.  if(ch==TAB)
  1244.   while((++y)&7);
  1245.  else
  1246.   y++;
  1247.  }
  1248. return y;
  1249. }
  1250.  
  1251. gocol(x)
  1252. TXTSIZ x;
  1253. {
  1254. TXTSIZ y;
  1255. int ch;
  1256. if(fmnrnl()) fmgetc();
  1257. extend=0;
  1258. for(y=0;y!=x;y++)
  1259.  {
  1260.  if(fmeof()) goto dn;
  1261.  ch=fmgetc();
  1262.  if(ch==NL)
  1263.   {
  1264.   fmpoint(fmnote()-1);
  1265.   extend=x;
  1266.   return;
  1267.   }
  1268.  if(ch==TAB)
  1269.   {
  1270.   while((++y)&7)
  1271.    {
  1272.    if(y==x)
  1273.     {
  1274.     fmpoint(fmnote()-1);
  1275. dn:
  1276.     extend=x;
  1277.     return;
  1278.     }
  1279.    }
  1280.   y--;
  1281.   }
  1282.  }
  1283. }
  1284.  
  1285. TXTSIZ calcs()
  1286. {
  1287. TXTSIZ y=0;
  1288. if(fmnrnl()) fmgetc();
  1289. extend=0;
  1290. while(! (fmeof()?1:fmrc()==NL))
  1291.  if(fmrc()==' ')
  1292.   {
  1293.   ++y;
  1294.   fmgetc();
  1295.   }
  1296.  else if(fmrc()==TAB)
  1297.   {
  1298.   do ++y; while(y%TABWIDTH);
  1299.   fmgetc();
  1300.   }
  1301.  else break;
  1302. return y;
  1303. }
  1304.  
  1305. unfill()
  1306. {
  1307. fmfnl();
  1308. extend=0;
  1309. while(fmnote())
  1310.  {
  1311.  unsigned char x=fmrgetc();
  1312.  if(x==' ' || x==TAB) fmdel(1);
  1313.  else
  1314.   {
  1315.   fmgetc();
  1316.   break;
  1317.   }
  1318.  }
  1319. }
  1320.  
  1321. /* Fill from end of line to extend position */
  1322.  
  1323. fillup()
  1324. {
  1325. TXTSIZ x;
  1326. if(extend && pic)
  1327.  {
  1328.  x=getrcol();
  1329.  while(extend>x)
  1330.   {
  1331.   fminsc(' ');
  1332.   fmgetc();
  1333.   ++x;
  1334.   }
  1335.  }
  1336. extend=0;
  1337. }
  1338.  
  1339. /* Save current buffer in named file.  Returns 0 on error.  Clears 'changed'
  1340.  * variable if sucessfull
  1341.  */
  1342.  
  1343. int saveit1(tos)
  1344. unsigned char *tos;
  1345. {
  1346. unsigned char sting[PATHSIZE];
  1347. TXTSIZ temp=fmnote();
  1348. fmpoint(0);
  1349. handle=fopen(tos,"w+");
  1350. if(handle)
  1351.  {
  1352.  if(!fmsave(handle,fmsize()))
  1353.   {
  1354.   sprintf(sting,"\\iError writing to file %s\\i",tos);
  1355.   msg(sting);
  1356.   fmpoint(temp);
  1357.   return(0);
  1358.   }
  1359.  fmpoint(temp);
  1360.  if(fclose(handle)==EOF)
  1361.   {
  1362.   sprintf(sting,"\\iError closing file %s\\i",tos);
  1363.   msg(sting);
  1364.   fmpoint(temp);
  1365.   return(0);
  1366.   }
  1367.  changed=0;
  1368.  curbuf->changed=0;
  1369.  return(1);
  1370.  }
  1371. else
  1372.  {
  1373.  sprintf(sting,"\\iError opening file %s\\i",tos);
  1374.  msg(sting);
  1375.  fmpoint(temp);
  1376.  return(0);
  1377.  }
  1378. }
  1379.  
  1380. rewrite()
  1381. {
  1382. unsigned char s[25];
  1383. int *t,c;
  1384. oxpos= 0;
  1385. oypos= 0;
  1386. tops= 0;
  1387. bots= height-1;
  1388. smode=0;
  1389. if(scroll) sprintf(s,"\033[m\033[1;%dr\033[H\033[J",height);
  1390. else sprintf(s,"\033[m\033[H\033[J");
  1391. eputs(s);
  1392. t=scrn;
  1393. c=width*height;
  1394. do *(t++)= ' '; while(--c);
  1395. upd=1;
  1396. newy=1;
  1397. updall=1;
  1398. if(helpon) hupd=1;
  1399. }
  1400.  
  1401. /* Toggle help text */
  1402.  
  1403. thelp()
  1404. {
  1405. struct window *x;
  1406. newy=1;
  1407. upd=1;
  1408. if(helpon)
  1409.  {
  1410.  x=topwin;
  1411.  do
  1412.   {
  1413.   if(x->hheight) x->height=x->hheight;
  1414.   else x->height*=height, x->height/=height-wind;
  1415.   x=x->next;
  1416.   }
  1417.   while(x!=topwin);
  1418.  wind=0, hupd=0;
  1419.  }
  1420. else
  1421.  {
  1422.  if(helplines>height-3) wind=height-3;
  1423.  else wind=helplines;
  1424.  hupd=1;
  1425.  x=topwin;
  1426.  do
  1427.   {
  1428.   x->hheight=x->height;
  1429.   x->height*=height-wind;
  1430.   x->height/=height;
  1431.   x=x->next;
  1432.   }
  1433.   while(x!=topwin);
  1434.  }
  1435. helpon= !helpon;
  1436. wfit();
  1437. }
  1438.  
  1439. /* Move cursor to beginning of file */
  1440.  
  1441. bof()
  1442. {
  1443. extend=0;
  1444. fmpoint(0);
  1445. newy=1;
  1446. }
  1447.  
  1448. /* Move cursor to beginning of line */
  1449.  
  1450. bol()
  1451. {
  1452. if(fmnrnl()) fmgetc();
  1453. extend=0;
  1454. }
  1455.  
  1456. /* Move cursor to end of line */
  1457.  
  1458. eol()
  1459. {
  1460. extend=0;
  1461. fmfnl();
  1462. }
  1463.  
  1464. /* Move cursor to end of file */
  1465.  
  1466. eof()
  1467. {
  1468. extend=0;
  1469. fmpoint(fmsize());
  1470. newy=1;
  1471. }
  1472.  
  1473. /* Move cursor right */
  1474.  
  1475. urtarw()
  1476. {
  1477. fillup();
  1478. extend=0;
  1479. if(fmeof())
  1480.  {
  1481.  if(pic)
  1482.   {
  1483.   into:
  1484.   fminsc(' ');
  1485.   fmgetc();
  1486.   }
  1487.  return;
  1488.  }
  1489. else if(fmrc()==NL)
  1490.  {
  1491.  if(pic) goto into;
  1492.  bol();
  1493.  udnarw();
  1494.  return;
  1495.  }
  1496. fmgetc();
  1497. }
  1498.  
  1499. rtarw()
  1500. {
  1501. fillup();
  1502. extend=0;
  1503. if(fmeof())
  1504.  {
  1505.  if(pic)
  1506.   {
  1507.   into:
  1508.   fminsc(' ');
  1509.   fmgetc();
  1510.   }
  1511.  return;
  1512.  }
  1513. else if(fmrc()==NL)
  1514.  {
  1515.  if(pic) goto into;
  1516.  newy=1;
  1517.  }
  1518. fmgetc();
  1519. }
  1520.  
  1521. ultarw()
  1522. {
  1523. if(extend)
  1524.  {
  1525.  extend=0;
  1526.  return;
  1527.  }
  1528. fillup();
  1529. if(fmnote())
  1530.  {
  1531.  fmpoint(fmnote()-1);
  1532.  if(fmrc()==NL)
  1533.   {
  1534.   fmgetc();
  1535.   uuparw();
  1536.   eol();
  1537.   }
  1538.  }
  1539. }
  1540.  
  1541. ltarw()
  1542. {
  1543. if(extend)
  1544.  {
  1545.  extend=0;
  1546.  return;
  1547.  }
  1548. fillup();
  1549. if(fmnote())
  1550.  fmpoint(fmnote()-1);
  1551. if(fmrc()==NL) newy=1;
  1552. }
  1553.  
  1554. /* Move cursor up */
  1555.  
  1556. uparw()
  1557. {
  1558. TXTSIZ x;
  1559. x=getcol();
  1560. bol();
  1561. if(fmnote())
  1562.  {
  1563.  fmpoint(fmnote()-1);
  1564.  if(fmnrnl())
  1565.   fmgetc();
  1566.  }
  1567. gocol(x);
  1568. newy=1;
  1569. }
  1570.  
  1571. /* user's cursor up routine (uses scrolling regions) */
  1572.  
  1573. uuparw()
  1574. {
  1575. TXTSIZ sve=fmnote();
  1576. int y=(curwin->wind+1)*width;
  1577. int x;
  1578. if(scroll)
  1579.  {
  1580.  if(fmnrnl())
  1581.   {
  1582.   if(fmnote()+1==saddr)
  1583.    {
  1584.    if(fmnrnl()) fmgetc();
  1585.    saddr=fmnote();
  1586.    setregn(curwin->wind+1,curwin->wind+(curwin->height-1));
  1587.    cpos(curwin->wind+1,oxpos);
  1588.    attrib(0);
  1589.    eputs("\033M");
  1590.    for(x=(curwin->wind+curwin->height)*width-1;x>=y+width;x--)
  1591.     scrn[x]=scrn[x-width];
  1592.    for(x=y;x<y+width;x++) scrn[x]= ' ';
  1593.    }
  1594.   fmpoint(sve);
  1595.   }
  1596.  else
  1597.   fmpoint(sve);
  1598.  }
  1599. uparw();
  1600. }
  1601.  
  1602. /* Move cursor down */
  1603.  
  1604. dnarw()
  1605. {
  1606. TXTSIZ x;
  1607. newy=1;
  1608. x=getcol();
  1609. if(!fmfnl())
  1610.  bol();
  1611. else
  1612.  fmgetc();
  1613. gocol(x);
  1614. }
  1615.  
  1616. /* user's down arrow function */
  1617.  
  1618. udnarw()
  1619. {
  1620. TXTSIZ sve=fmnote();
  1621. int x;
  1622. if(!fmfnl())
  1623.  {
  1624.  if(pic)
  1625.   {
  1626.   fminsc(NL);
  1627.   fmpoint(sve);
  1628.   udnarw();
  1629.   return;
  1630.   }
  1631.  else
  1632.   {
  1633.   goto cant;
  1634.   }
  1635.  }
  1636. if(scroll)
  1637.  {
  1638.  if(ypos!=curwin->height+curwin->wind-1) goto cant;
  1639.  for(x=0;x!=curwin->height-2;x++) fmnrnl();
  1640.  fmfnl();
  1641.  fmgetc();
  1642.  saddr=fmnote();
  1643.  setregn(curwin->wind+1,curwin->wind+curwin->height-1);
  1644.  cpos((curwin->wind+curwin->height-1),oxpos);
  1645.  attrib(0);
  1646.  eputc(10);
  1647.  for(x=(curwin->wind+1)*width;x!=(curwin->wind+curwin->height-1)*width;x++)
  1648.   scrn[x]=scrn[x+width];
  1649.  for(x=(curwin->wind+curwin->height-1)*width;
  1650.      x!=(curwin->wind+curwin->height)*width;x++)
  1651.   scrn[x]= ' ';
  1652.  }
  1653. cant:
  1654. fmpoint(sve);
  1655. dnarw();
  1656. }
  1657.  
  1658. /* Magic Tabs (tm) */
  1659.  
  1660. TXTSIZ tabcol;    /* Original column of text preceeded by tab stops */
  1661.  
  1662. tabmark()
  1663. {
  1664. TXTSIZ cur=fmnote();
  1665. unsigned char c;
  1666. tabcol=0;
  1667. if(!tabmagic) return;
  1668. while(!fmeof())
  1669.  {
  1670.  c=fmgetc();
  1671.  if(c=='\t')
  1672.   {
  1673.   while(!fmeof())
  1674.    {
  1675.    c=fmgetc();
  1676.    if(c=='\n') break;
  1677.    if(c!='\t')
  1678.     {
  1679.     fmrgetc();
  1680.     tabcol=getrcol();
  1681.     break;
  1682.     }
  1683.    }
  1684.   fmpoint(cur); return;
  1685.   }
  1686.  if(c=='\n') break;
  1687.  }
  1688. fmpoint(cur); return;
  1689. }
  1690.  
  1691. tabfix()
  1692. {
  1693. TXTSIZ cur=fmnote(),newcol;
  1694. unsigned char c;
  1695. if(!tabcol) return;
  1696. while(!fmeof())
  1697.  {
  1698.  c=fmgetc();
  1699.  if(c=='\t')
  1700.   {
  1701.   while(!fmeof())
  1702.    {
  1703.    c=fmgetc();
  1704.    if(c=='\n') break;
  1705.    if(c!='\t')
  1706.     {
  1707.     fmrgetc();
  1708.     newcol=getrcol();
  1709.     while(newcol<tabcol)
  1710.      {
  1711.      fminsc('\t');
  1712.      newcol+=8;
  1713.      }
  1714.     fmrgetc();
  1715.     while(newcol>tabcol)
  1716.      {
  1717.      if(fmrgetc()=='\t')
  1718.       {
  1719.       fmdel(1);
  1720.       newcol-=8;
  1721.       }
  1722.      else break;
  1723.      }
  1724.     break;
  1725.     }
  1726.    }
  1727.   fmpoint(cur); return;
  1728.   }
  1729.  if(c=='\n') break;
  1730.  }
  1731. fmpoint(cur); return;
  1732. }
  1733.  
  1734. /* Delete character under cursor */
  1735.  
  1736. delch()
  1737. {
  1738. unsigned char c;
  1739. int x;
  1740. if(extend && pic) return;
  1741. if(extend)
  1742.  {
  1743.  extend=0;
  1744.  return;
  1745.  }
  1746. if(!fmeof())
  1747.  {
  1748.  if((c=fmrc())==NL && scroll)
  1749.   {
  1750.   if(ypos<curwin->wind+curwin->height-2)
  1751.    {
  1752.    for(x=(ypos+1)*width;x<width*(curwin->wind+curwin->height-1);x++)
  1753.     scrn[x]=scrn[x+width];
  1754.    for(x=(curwin->wind+curwin->height-1)*width;
  1755.    x<(curwin->wind+curwin->height)*width;x++) scrn[x]= ' ';
  1756.    setregn(ypos+1,(curwin->wind+curwin->height-1));
  1757.    cpos((curwin->wind+curwin->height-1),oxpos);
  1758.    attrib(0);
  1759.    eputc(10);
  1760.    }
  1761.   fmdel(1);
  1762.   }
  1763.  else if(c==TAB) fmdel(1);
  1764.  else
  1765.   {
  1766.   tabmark();
  1767.   fmdel(1);
  1768.   tabfix();
  1769.   }
  1770.  }
  1771. }
  1772.  
  1773. type(ch)
  1774. unsigned char ch;
  1775. {
  1776. int ox=oxpos;
  1777. int x,y;
  1778. TXTSIZ temp, temp1;
  1779. int eflag=0;
  1780. if(quote8th)
  1781.  {
  1782.  quote8th=0;
  1783.  ch|=128;
  1784.  }
  1785. ypos=oypos;
  1786. if(extend)
  1787.  {
  1788.  if(ch!=NL) fillup();
  1789.  else extend=0;
  1790.  eflag=1;
  1791.  }
  1792. if(ch==NL)
  1793.  {
  1794.  if(overwrite && !tabmagic && !fmeof()) fmdel(1);
  1795.  fminsc(ch);
  1796.  fmgetc();
  1797.  newy=1;
  1798.  if(ypos!=(curwin->wind+curwin->height-1))
  1799.   {
  1800.   if(!fmeof())
  1801.    {
  1802.    if(ypos<curwin->wind+curwin->height-2 && scroll)
  1803.     {
  1804.     setregn(ypos+1,(curwin->wind+curwin->height-1));
  1805.     cpos(ypos+1,oxpos);
  1806.     attrib(0);
  1807.     eputs("\033M");
  1808.     cpos(ypos+1,0);
  1809.     for(x=(curwin->wind+curwin->height)*width-1;x>=(ypos+2)*width;x--)
  1810.      scrn[x]=scrn[x-width];
  1811.     for(x=(ypos+1)*width;x<(ypos+2)*width;x++) scrn[x]=' ';
  1812.     }
  1813.    else cpos(ypos+1,0);
  1814.    }
  1815.   else
  1816.    cpos(ypos+1,0);
  1817.   }
  1818.  else if(scroll)
  1819.    {
  1820.    setregn(curwin->wind+1,(curwin->wind+curwin->height-1));
  1821.    cpos((curwin->height+curwin->wind-1),0);
  1822.    attrib(0);
  1823.    eputc(10);
  1824.    for(x=curwin->wind*width;x<(curwin->wind+curwin->height-1)*width;x++)
  1825.     scrn[x]=scrn[x+width];
  1826.    for(x=(curwin->wind+curwin->height-1)*width;
  1827.        x<(curwin->wind+curwin->height)*width;x++) scrn[x]= ' ';
  1828.    temp=fmnote();
  1829.    fmpoint(saddr);
  1830.    fmfnl();
  1831.    fmgetc();
  1832.    saddr=fmnote();
  1833.    fmpoint(temp);
  1834.    }
  1835.  if(ox<(width-2) && (fmeof()) && scroll) uuu=1;
  1836.  if(autoind)
  1837.   {
  1838.   temp=fmnote();
  1839.   uparw();
  1840.   for(x=0;1;x++)
  1841.    {
  1842.    ch=fmgetc();
  1843.    if(!(ch==' ' || ch==TAB)) break;
  1844.    temp1=fmnote();
  1845.    fmpoint(temp);
  1846.    fminsc(ch);
  1847.    uuu=0;
  1848.    added++;
  1849.    fmpoint(temp1);
  1850.    temp++;
  1851.    }
  1852.   fmpoint(fmnote()-(x+1));
  1853.   dnarw();
  1854.   y=overwrite, overwrite=0;
  1855.   for(;x;x--) rtarw();
  1856.   overwrite=y;
  1857.   }
  1858.  }
  1859. else
  1860.  {
  1861.  if(overwrite)
  1862.   {
  1863.   if(!tabmagic)
  1864.    {
  1865.    if(!fmeof())
  1866.     {
  1867.     unsigned char c=fmrc();
  1868.     fmdel(1);
  1869.     if(ch!=TAB && c!=TAB && c!=NL && ox<(width-2)) uuu=1;
  1870.     }
  1871.    else if(ch!=TAB && ox<(width-2)) uuu=1;
  1872.    }
  1873.   else
  1874.    if(fmrc()!=NL && !fmeof())
  1875.     if(ch==TAB && fmrc()!=TAB)
  1876.      {
  1877.      TXTSIZ foo=getrcol();
  1878.      do
  1879.       {
  1880.       if(fmeof()) break;
  1881.       if(fmrc()==NL) break;
  1882.       if(fmrc()==TAB)
  1883.        {
  1884.        fmdel(1);
  1885.        break;
  1886.        }
  1887.       else fmdel(1);
  1888.       ++foo;
  1889.       }
  1890.       while(foo&7);
  1891.      }
  1892.     else if(ch!=TAB && fmrc()==TAB)
  1893.      {
  1894.      TXTSIZ tt;
  1895.      tabmark();
  1896.      if(tt=tabcol)
  1897.       {
  1898.       fminsc(ch);
  1899.       tabmark();
  1900.       fmdel(1);
  1901.       if(tabcol!=tt) fmdel(1);
  1902.       }
  1903.      }
  1904.     else
  1905.      {
  1906.      fmdel(1);
  1907.      if(ch!=TAB && ox<(width-2)) uuu=1;
  1908.      }
  1909.    else if(ox<(width-2) && ch!=TAB) uuu=1;
  1910.   }
  1911.  if(wrap)
  1912.   {
  1913.   unsigned char xx;
  1914.   if(getrcol()<rmargin) goto skip;
  1915.   if(ch==' ')
  1916.    fminsc(' '), rtarw();
  1917.   else
  1918.    {
  1919.    temp=fmnote();
  1920.    while(1)
  1921.     {
  1922.     if(fmnote())
  1923.      {
  1924.      fmpoint(fmnote()-1);
  1925.      xx=fmrc();
  1926.      if(xx==NL) break;
  1927.      if(xx==' ' || x==TAB)
  1928.       {
  1929.       fmdel(1);
  1930.       added=0;
  1931.       type(NL);
  1932.       temp+=added;
  1933.       break;
  1934.       }
  1935.      }
  1936.     else break;
  1937.     }
  1938.    fmpoint(temp);
  1939.    fminsc(ch);
  1940.    rtarw();
  1941.    uuu=0;
  1942.    }
  1943.   }
  1944.  else
  1945.   {
  1946. skip:
  1947.   if(overwrite || ch==TAB) fminsc(ch);
  1948.   else
  1949.    {
  1950.    tabmark();
  1951.    fminsc(ch);
  1952.    tabfix();
  1953.    }
  1954.   if(ch!=TAB && ch!=NL)
  1955.    {
  1956.    int cc=showas(ch);
  1957.    if(fmnote()>=markb && fmnote()<marke) cc^=INVERSE;
  1958.    fmgetc();
  1959.    tputcc(cc);
  1960.    scrn[ypos*width+oxpos]=cc;
  1961.    oxpos++;
  1962.    if(fmeof()) { if(!eflag && ox<width-2) uuu=1; }
  1963.    else if(fmrc()==NL && !eflag && ox<width-2) uuu=1;
  1964.    }
  1965.   else fmgetc();
  1966.   }
  1967.  }
  1968. }
  1969.  
  1970. itype(ch)
  1971. unsigned char ch;
  1972. {
  1973. int x,y;
  1974. TXTSIZ temp,temp1;
  1975. if(extend)
  1976.  {
  1977.  if(ch!= NL) fillup();
  1978.  else extend=0;
  1979.  }
  1980. if(ch==NL)
  1981.  {
  1982.  fminsc(ch);
  1983.  fmgetc();
  1984.  newy=1;
  1985.  if(autoind)
  1986.   {
  1987.   temp=fmnote();
  1988.   uparw();
  1989.   for(x=0;1;x++)
  1990.    {
  1991.    ch=fmgetc();
  1992.    if(!(ch==' ' || ch==TAB)) break;
  1993.    temp1=fmnote();
  1994.    fmpoint(temp);
  1995.    fminsc(ch);
  1996.    added++;
  1997.    fmpoint(temp1);
  1998.    temp++;
  1999.    }
  2000.   fmpoint(fmnote()-(x+1));
  2001.   dnarw();
  2002.   y=overwrite, overwrite=0;
  2003.   for(;x;x--) rtarw();
  2004.   overwrite=y;
  2005.   }
  2006.  }
  2007. else
  2008.  {
  2009.  if(overwrite)
  2010.   if(!fmeof()) fmdel(1);
  2011.  if(wrap)
  2012.   {
  2013.   if(getrcol()<rmargin) goto skip;
  2014.   if(ch==' ')
  2015.    fminsc(' '), rtarw();
  2016.   else
  2017.    {
  2018.    temp=fmnote();
  2019.    while(1)
  2020.     {
  2021.     if(fmnote())
  2022.      {
  2023.      fmpoint(fmnote()-1);
  2024.      x=fmrc();
  2025.      if(x==NL) break;
  2026.      if(x==' ' || x==TAB)
  2027.       {
  2028.       fmdel(1);
  2029.       added=0;
  2030.       itype(NL);
  2031.       temp+=added;
  2032.       break;
  2033.       }
  2034.      }
  2035.     else break;
  2036.     }
  2037.    fmpoint(temp);
  2038.    fminsc(ch);
  2039.    rtarw();
  2040.    }
  2041.   }
  2042.  else
  2043.   {
  2044. skip:
  2045.   fminsc(ch);
  2046.   rtarw();
  2047.   }
  2048.  }
  2049. }
  2050.  
  2051. /* Insert space */
  2052.  
  2053. inss()
  2054. {
  2055. int t=overwrite;
  2056. if(extend)
  2057.  {
  2058.  extend=0;
  2059.  return;
  2060.  }
  2061. overwrite=0;
  2062. type(' ');
  2063. ltarw();
  2064. overwrite=t;
  2065. }
  2066.  
  2067. /* Deleting backspace */
  2068.  
  2069. backs()
  2070. {
  2071. int flag=0,c;
  2072. if(extend)
  2073.  {
  2074.  extend=0;
  2075.  return;
  2076.  }
  2077. if(fmeof()) c=1;
  2078. else if(fmrc()==NL) c=1;
  2079. if(fmnote())
  2080.  {
  2081.  ultarw();
  2082.  if(fmrc()==TAB) flag=1;
  2083.  if(overwrite && !tabmagic)
  2084.   {
  2085.   itype(' ');
  2086.   ultarw();
  2087.   }
  2088.  else if(overwrite && tabmagic)
  2089.   {
  2090.   if(c) delch();
  2091.   else if(!flag)
  2092.    {
  2093.    itype(' ');
  2094.    ltarw();
  2095.    }
  2096.   }
  2097.  else delch();
  2098.  if(oxpos && !flag)
  2099.   {
  2100.   eputc(8), tputcc(32), eputc(8), oxpos--,scrn[oypos*width+oxpos]=32;
  2101.   if(fmeof()) uuu=1;
  2102.   else if(fmrc()==NL || overwrite) uuu=1;
  2103.   }
  2104.  }
  2105. }
  2106.  
  2107. /* quit: exit without saving */
  2108.  
  2109. eexit()
  2110. {
  2111. int c;
  2112. if(curwin->next==curwin)
  2113.  {
  2114.  if(changed)
  2115.   {
  2116.   c=askyn("Do you really want to throw away this file?"); 
  2117.   if(c=='N') return;
  2118.   if(c== -1) return;
  2119.   dclose();
  2120.   eputs("\nFile not saved.\r\n");
  2121.   }
  2122.  else
  2123.   {
  2124.   dclose();
  2125.   eputs("\nFile not changed so no update needed\r\n");
  2126.   }
  2127.  leave=1;
  2128.  }
  2129. else
  2130.  {
  2131.  struct window *t=curwin;
  2132.  if(changed && curbuf->count==1)
  2133.   {
  2134.   c=askyn("Do you really want to throw away this file?");
  2135.   if(c=='N') return;
  2136.   if(c== -1) return;
  2137.   }
  2138.  if(curbuf->count==1)
  2139.   {
  2140.   killundo();
  2141.   killredo();
  2142.   free(curbuf->buf), free(curbuf);
  2143.   if(curbuf==markbuf) markbuf=0;
  2144.   }                           
  2145.  else curbuf->count--;
  2146.  curwin->next->prev=curwin->prev;
  2147.  curwin->prev->next=curwin->next;
  2148.  curwin=curwin->prev;
  2149.  free(t);
  2150.  ldwin(curwin);
  2151.  if(topwin==t) topwin=curwin;
  2152.  wfit();
  2153.  }
  2154. }
  2155.  
  2156. pgup()
  2157. {
  2158. int nlins=curwin->height-1;
  2159. int hlins=nlins/2;
  2160. int x,y;
  2161. TXTSIZ curpos,z;
  2162. if(!hlins) hlins=1;
  2163. z=getcol();
  2164. curpos=fmnote();
  2165. fmpoint(saddr);
  2166. for(x=0;x<hlins;x++)
  2167.  {
  2168.  if(!fmnrnl())
  2169.   {
  2170.   if(!x)
  2171.    {
  2172.    gocol(z);
  2173.    newy=1;
  2174.    return;
  2175.    }
  2176.   else
  2177.    break;
  2178.   }
  2179.  }
  2180. if(fmnrnl()) fmgetc();
  2181. saddr=fmnote();
  2182. fmpoint(curpos);
  2183. setregn(curwin->wind+1,(curwin->wind+curwin->height-1));
  2184. cpos(curwin->wind+1,oxpos);
  2185. attrib(0);
  2186. for(y=0;y<x;y++)
  2187.  {
  2188.  if(scroll) eputs("\033M");
  2189.  fmnrnl();
  2190.  }
  2191. if(fmnrnl()) fmgetc();
  2192. cpos(oypos,oxpos);
  2193. gocol(z);
  2194. x*=width;
  2195. if(scroll) for(y=(curwin->wind+1)*width;y<x+(curwin->wind+1)*width;y++)
  2196.  {
  2197.  scrn[y+x]=scrn[y];
  2198.  scrn[y]= ' ';
  2199.  }
  2200. }
  2201.  
  2202. pgdn()
  2203. {
  2204. int nlins=curwin->height-1;
  2205. int hlins=nlins/2;
  2206. TXTSIZ curpos,z;
  2207. int x,y;
  2208. z=getcol();
  2209. curpos=fmnote();
  2210. x=nlins;
  2211. fmpoint(saddr);
  2212. do
  2213.  {
  2214.  if(fmfnl()) fmgetc();
  2215.  else
  2216.   {
  2217.   newy=1;
  2218.   gocol(z);
  2219.   return;
  2220.   }
  2221.  }
  2222.  while(--x);
  2223. for(x=1;x<hlins;x++)
  2224.  {
  2225.  if(fmfnl()) fmgetc();
  2226.  else break;
  2227.  }
  2228.  
  2229. fmpoint(saddr);
  2230. for(y=0;y<x;y++)
  2231.  {
  2232.  fmfnl();
  2233.  fmgetc();
  2234.  }
  2235. saddr=fmnote();
  2236.  
  2237. setregn(curwin->wind+1,(curwin->wind+curwin->height-1));
  2238. cpos((curwin->wind+curwin->height-1),oxpos);
  2239. fmpoint(curpos);
  2240. attrib(0);
  2241. for(y=0;y<x;y++)
  2242.  {
  2243.  fmfnl();
  2244.  fmgetc();
  2245.  if(scroll) eputc(10);
  2246.  }
  2247.  
  2248. gocol(z);
  2249. cpos(ypos,xpos);
  2250. if(scroll)
  2251.  {
  2252.  y=width*x;
  2253.  for(curpos=(curwin->wind+1)*width+y;curpos<(curwin->wind+curwin->height)*
  2254.      width;curpos++)
  2255.   scrn[curpos-y]=scrn[curpos];
  2256.  for(curpos=(curwin->wind+curwin->height)*width-width*x;
  2257.      curpos<(curwin->wind+curwin->height)*width;curpos++)
  2258.   scrn[curpos]= ' ';
  2259.  }
  2260. }
  2261.  
  2262. deleol()
  2263. {
  2264. TXTSIZ temp=fmnote();
  2265. TXTSIZ temp1;
  2266. if(extend && pic) return;
  2267. extend=0;
  2268. fmfnl();
  2269. temp1=fmnote()-temp;
  2270. fmpoint(temp);
  2271. if(temp1) fmdel(temp1);
  2272. }
  2273.  
  2274. killlin()
  2275. {
  2276. extend=0;
  2277. if(!fmeof())
  2278.  {
  2279.  if(fmrc()==NL) delch();
  2280.  else deleol();
  2281.  }
  2282. }
  2283.  
  2284. dellin()
  2285. {
  2286. bol();
  2287. deleol();
  2288. delch();
  2289. }
  2290.  
  2291. fixpath(s)
  2292. unsigned char *s;
  2293. {
  2294. unsigned char tmp[PATHSIZE], *p, c;
  2295. struct passwd *passwd;
  2296. if(*s=='~')
  2297.  {
  2298.  p=s+1;
  2299.  while(*p!='/' && *p) ++p;
  2300.  if(c= *p)
  2301.   {
  2302.   *p=0;
  2303.   if(!s[1])
  2304.    {
  2305.    *p=c;
  2306.    strcpy(tmp,getenv("HOME"));
  2307.    strcat(tmp,p);
  2308.    strcpy(s,tmp);
  2309.    }
  2310.   else if(passwd=getpwnam(s+1))
  2311.    {
  2312.    *p=c;
  2313.    strcpy(tmp,passwd->pw_dir);
  2314.    strcat(tmp,p);
  2315.    strcpy(s,tmp);
  2316.    }
  2317.   }
  2318.  }
  2319. }
  2320.  
  2321. /*
  2322.  
  2323. struct list
  2324.  {
  2325.  struct list *next;
  2326.  unsigned char *name;
  2327.  };
  2328.  
  2329. unsigned char *complete(list,name)
  2330. struct list *list;
  2331. unsigned char *name;
  2332. {
  2333. struct list *found=0;
  2334. int x;
  2335. while(list)
  2336.  {
  2337.  for(x=0;name[x] && list->name[x];++x) if(name[x]!=list->name[x]) goto next;
  2338.  if(found) return 0;
  2339.  found=list;
  2340.  next:
  2341.  list=list->next;
  2342.  }
  2343. if(found) return found->name;
  2344. else return 0;
  2345. }
  2346.  
  2347. struct list *getnames(name)
  2348. unsigned char *name;
  2349. {
  2350. DIR *dir=opendir(name);
  2351. struct direct *dirent;
  2352. struct list *first=0, *next=0;
  2353. if(dir)
  2354.  {
  2355.  while(dirent=readdir(dir))
  2356.   {
  2357.   if(next) next=next->next=malloc(sizeof(struct list));
  2358.   else first=next=malloc(sizeof(struct list));
  2359.   next->next=0;
  2360.   next->name=strdupp(dirent->d_name);
  2361.   }
  2362.  closedir(dir);
  2363.  }
  2364. return first;
  2365. }
  2366.  
  2367. rmlist(list)
  2368. struct list *list;
  2369. {
  2370. struct list *nxt;
  2371. if(list)
  2372.  do
  2373.   nxt=list->next, free(list);
  2374.   while(list=nxt);
  2375. }
  2376.  
  2377. docomplete(s)
  2378. unsigned char *s;
  2379. {
  2380. struct list *list=getnames(".");
  2381. unsigned char *name;
  2382. if(!list) return;
  2383. name=complete(list,s);
  2384. if(name) strcpy(s,name);
  2385. else eputc(7);
  2386. rmlist(list);
  2387. }
  2388.  
  2389. */
  2390.  
  2391. exsave()
  2392. {
  2393. unsigned char sting[PATHSIZE];
  2394. if(!changed)
  2395.  {
  2396.  eexit();
  2397.  return;
  2398.  }
  2399. if(gfnam[0]==0)
  2400.  {
  2401.  if(!getl("Save file",gfnam))
  2402.   return;
  2403.  fixpath(gfnam);
  2404.  }
  2405. else if(!backup)
  2406.  {
  2407.  sprintf(sting,"/bin/cp %s %s~",gfnam,gfnam);
  2408.  cpos(height-2,0);
  2409.  system(sting);
  2410.  cpos(ypos,xpos);
  2411.  }
  2412. if(saveit1(gfnam))
  2413.  {
  2414.  sprintf(sting,"\nFile %s saved.\r\n",gfnam);
  2415.  if(curwin->next==curwin)
  2416.   {
  2417.   dclose();
  2418.   eputs(sting);
  2419.   leave=1;
  2420.   }
  2421.  else
  2422.   eexit();
  2423.  }
  2424. }
  2425.  
  2426. saveit()
  2427. {
  2428. unsigned char gfnam1[PATHSIZE];
  2429. unsigned char sting[PATHSIZE];
  2430. strcpy(gfnam1,gfnam);
  2431. if(!getl("Save file",gfnam1))
  2432.  return;
  2433. fixpath(gfnam1);
  2434. if(!gfnam1[0]) return;
  2435. if(!backup && !strcmp(gfnam1,gfnam))
  2436.  {
  2437.  sprintf(sting,"/bin/cp %s %s~",gfnam,gfnam);
  2438.  cpos(height-2,0);
  2439.  system(sting);
  2440.  cpos(ypos,xpos);
  2441.  }
  2442. saveit1(gfnam1);
  2443. }
  2444.  
  2445. findline()
  2446. {
  2447. unsigned char sting[PATHSIZE];
  2448. TXTSIZ x;
  2449. sting[0]=0;
  2450. if(!getl("Goto line",sting))
  2451.  return;
  2452. x=atol(sting);
  2453. if(!x)
  2454.  {
  2455.  msg("\\iBad line number\\i");
  2456.  return;
  2457.  }
  2458. x--;
  2459. bof();
  2460. for(;x;x--)
  2461.  {
  2462.  if(!fmfnl()) break;
  2463.  fmgetc();
  2464.  }
  2465. newy=1;
  2466. cntr=1;
  2467. return;
  2468. }
  2469.  
  2470. repeat()
  2471. {
  2472. unsigned char sting[PATHSIZE];
  2473. TXTSIZ x;
  2474. sting[0]=0;
  2475. if(!getl("Repeat",sting))
  2476.  return;
  2477. x=atol(sting);
  2478. nrepeatamnt=x;
  2479. }
  2480.  
  2481. int search()
  2482. {
  2483. if(options&s_backwards)
  2484.  {
  2485.  while(fmnote())
  2486.   {
  2487.   fmrgetc();
  2488.   if(options&s_ignore) { if(!fmicmp(sstring,len)) return 1; }
  2489.   else if(!fmcmp(sstring,len)) return 1;
  2490.   }
  2491.  return 0;
  2492.  }
  2493. else
  2494.  {
  2495.  while(fmnote()+len<=fmsize())
  2496.   {
  2497.   if(!(options&s_ignore)) { if(!fmcmp(sstring,len)) return 1; }
  2498.   else if(!fmicmp(sstring,len)) return 1;
  2499.   fmgetc();
  2500.   }
  2501.  return 0;
  2502.  }
  2503. }
  2504.  
  2505. find(c)
  2506. {
  2507. int x;
  2508. int opts=0;
  2509. int n=0;
  2510. int rest=0;
  2511. int rlen;
  2512. TXTSIZ p;
  2513. unsigned char ss[80];
  2514. extend=0;
  2515. if(c=='L'-'@' && sstring[0]) goto srch;
  2516. ss[0]=0;
  2517. if(!(x=getl("Search string",ss))) return;
  2518. if(x== -1)
  2519.  {
  2520.  if(ss[0])
  2521.   strcpy(sstring,ss);
  2522.  goto srch;
  2523.  }
  2524. if(!ss[0]) return;
  2525. strcpy(sstring,ss);
  2526. ss[0]=0;
  2527. if(!getl("(I)gnore case (B)ackwards (R)eplace n",ss)) return;
  2528. for(x=0;ss[x];x++)
  2529.  {
  2530.  if(ss[x]=='i' || ss[x]=='I') opts|=s_ignore;
  2531.  if(ss[x]=='b' || ss[x]=='B') opts|=s_backwards;
  2532.  if(ss[x]=='r' || ss[x]=='R') opts|=s_replace;
  2533.  if(ss[x]=='x' || ss[x]=='X') opts|=s_regex;
  2534.  if(ss[x]>='0' && ss[x]<='9') n*=10, n+=ss[x]-'0';
  2535.  }
  2536. options=opts;
  2537. if(options&s_replace)
  2538.  {
  2539.  ss[0]=0;
  2540.  if(!(x=getl("Replace with",ss))) return;
  2541.  if(x!= -1)
  2542.   strcpy(rstring,ss);
  2543.  }
  2544. srch:
  2545. if(!sstring[0]) return;
  2546. len=strlen(sstring);
  2547. rlen=strlen(rstring);
  2548. rpt:
  2549. p=fmnote();
  2550. if(search())
  2551.  {
  2552.  if(!(options&s_backwards)) fmpoint(fmnote()+len);
  2553.  if(options&s_replace)
  2554.   {
  2555.   if(rest) goto dn;
  2556.   newy=1;
  2557.   upd=1;
  2558.   cntr=1;
  2559.   extend=0;
  2560.   dupdate();
  2561. again:
  2562.   x=nquery(
  2563.   "Replace? (Yes, No, ^C to abort or R to replace rest without asking)");
  2564.   if(x=='n' || x=='N') goto rpt;
  2565.   if(x== 3) return;
  2566.   if(x=='y' || x=='Y') goto dn;
  2567.   if(x=='r' || x=='R')
  2568.    {
  2569.    rest=1;
  2570.    goto dn;
  2571.    }
  2572.   goto again;
  2573. dn:
  2574.   if(options&s_backwards)
  2575.    {
  2576.    fmdel(len);
  2577.    fminss(rstring,rlen);
  2578.    }
  2579.   else
  2580.    {
  2581.    fmpoint(fmnote()-len);
  2582.    fmdel(len);
  2583.    fminss(rstring,rlen);
  2584.    fmpoint(fmnote()+rlen);
  2585.    }
  2586.   if(n)
  2587.    if(n==1) goto exi;
  2588.    else n--;
  2589.   goto rpt;
  2590.   }
  2591.  else if(n)
  2592.   {
  2593.   if(n==1) goto exi;
  2594.   n--;
  2595.   goto rpt;
  2596.   }
  2597.  }
  2598. else
  2599.  {
  2600.  if(!(options&s_replace) || n>1)
  2601.   msg("Not found");
  2602.  fmpoint(p);
  2603.  return;
  2604.  }
  2605. exi:
  2606. cntr=1;
  2607. newy=1;
  2608. }
  2609.  
  2610. findnext()
  2611. {
  2612. find('L'-'@');
  2613. }
  2614.  
  2615. findfirst()
  2616. {
  2617. find(0);
  2618. }
  2619.  
  2620. struct buffer *markbuf;
  2621.  
  2622. setbeg()
  2623. {
  2624. markb=fmnote();
  2625. if(markbuf!=curbuf)
  2626.  {
  2627.  markbuf=curbuf;
  2628.  marke=0;
  2629.  }
  2630. }
  2631.  
  2632. setend()
  2633. {
  2634. marke=fmnote();
  2635. if(markbuf!=curbuf)
  2636.  {
  2637.  markbuf=curbuf;
  2638.  markb=0;
  2639.  }
  2640. }
  2641.  
  2642. writeblk()
  2643. {
  2644. unsigned char gfnam1[PATHSIZE];
  2645. unsigned char sting[PATHSIZE];
  2646. TXTSIZ sv=fmnote();
  2647. struct buffer *bt=curbuf;
  2648. if(markbuf)
  2649.  {
  2650.  stbuf(curbuf);
  2651.  ldbuf(markbuf);
  2652.  }
  2653. if(markb>=marke || marke>fmsize() || !markbuf)
  2654.  {
  2655.  msg("\\iNo block\\i");
  2656.  if(markbuf)
  2657.   ldbuf(bt);
  2658.  return;
  2659.  }
  2660. gfnam1[0]=0;
  2661. if(!getl("File to write block to",gfnam1))
  2662.  {
  2663.  ldbuf(bt);
  2664.  return;
  2665.  }
  2666. fixpath(gfnam1);
  2667. handle=fopen(gfnam1,"w+");
  2668. if(handle)
  2669.  {
  2670.  fmpoint(markb);
  2671.  if(!fmsave(handle,marke-markb))
  2672.   {
  2673.   sprintf(sting,"\\iError writting to file %s\\i",gfnam1);
  2674.   msg(sting);
  2675.   }
  2676.  stbuf(markbuf);
  2677.  ldbuf(bt);
  2678.  fmpoint(sv);
  2679.  fclose(handle);
  2680.  }
  2681. else
  2682.  {
  2683.  ldbuf(bt);
  2684.  sprintf(sting,"\\iError opening file %s\\i",gfnam1);
  2685.  msg(sting);
  2686.  }
  2687. }
  2688.  
  2689. cmdblk()
  2690. {
  2691. unsigned char ch;
  2692. int fr[2];
  2693. int fw[2];
  2694. unsigned char gfnam1[PATHSIZE];
  2695. unsigned char sting[PATHSIZE];
  2696. TXTSIZ sv=fmnote(), sz;
  2697. struct buffer *bt=curbuf;
  2698. if(markbuf)
  2699.  {
  2700.  stbuf(curbuf);
  2701.  ldbuf(markbuf);
  2702.  }
  2703. if(markb>=marke || marke>fmsize() || !markbuf)
  2704.  {
  2705.  marke=markb=0;
  2706.  markbuf=bt;
  2707.  }
  2708. gfnam1[0]=0;
  2709. if(markb==marke)
  2710.  {
  2711.  if(!getl("Command to capture:",gfnam1))
  2712.   {
  2713.   ldbuf(bt);
  2714.   return;
  2715.   }
  2716.  }
  2717. else if(!getl("Command to pipe block through:",gfnam1))
  2718.  {
  2719.  ldbuf(bt);
  2720.  return;
  2721.  }
  2722. fixpath(gfnam1);
  2723. pipe(fr);
  2724. pipe(fw);
  2725. dclose();
  2726. eputc('\n');
  2727. aclose();
  2728. if(!fork())
  2729.  {
  2730.  signorm();
  2731.  printf("%s\n",gfnam1);
  2732.  if(markb!=marke) close(0);
  2733.  close(1);
  2734.  if(markb!=marke) dup(fw[0]);
  2735.  dup(fr[1]);
  2736.  close(fw[0]);
  2737.  close(fr[1]);
  2738.  close(fw[1]);
  2739.  close(fr[0]);
  2740.  execl("/bin/sh","/bin/sh","-c",gfnam1,0);
  2741.  exit(0);
  2742.  }
  2743. close(fr[1]);
  2744. close(fw[0]);
  2745. if(fork())
  2746.  {
  2747.  if(bt==markbuf) if(sv>=markb && sv<marke) sv=markb;
  2748.  sz=marke-markb;
  2749.  fmpoint(markb);
  2750.  if(sz) fmdel(sz);
  2751.  if(bt==markbuf) if(sv>markb) sv-=sz;
  2752.  close(fw[1]);
  2753.  stbuf(markbuf);
  2754.  ldbuf(bt);
  2755.  fmpoint(sv);
  2756.  markbuf=bt;
  2757.  markb=sv;
  2758.  while(1==read(fr[0],&ch,1)) putchar(ch), fminsc(ch), fmgetc();
  2759.  fflush(stdout);
  2760.  close(fr[0]);
  2761.  marke=fmnote();
  2762.  fmpoint(markb);
  2763.  wait(0);
  2764.  wait(0);
  2765.  }
  2766. else
  2767.  {
  2768.  fmpoint(markb);
  2769.  while(fmnote()!=marke)
  2770.   {
  2771.   ch=fmgetc();
  2772.   write(fw[1],&ch,1);
  2773.   }
  2774.  close(fw[1]);
  2775.  _exit();
  2776.  }
  2777. aopen();
  2778. rewrite();
  2779. updall=1;
  2780. newy=1;
  2781. }
  2782.  
  2783. delblk()
  2784. {
  2785. struct buffer *bt=curbuf;
  2786. TXTSIZ x=fmnote();
  2787. TXTSIZ sz;
  2788. if(markbuf)
  2789.  {
  2790.  stbuf(curbuf);
  2791.  ldbuf(markbuf);
  2792.  }
  2793. if(marke<=markb || marke>fmsize() || !markbuf)
  2794.  {
  2795.  msg("\\iNo block\\i");
  2796.  if(markbuf)
  2797.   ldbuf(bt);
  2798.  return;
  2799.  }
  2800. if(bt==markbuf) if(x>=markb && x<marke) x=markb;
  2801. sz=marke-markb;
  2802. fmpoint(markb);
  2803. fmdel(sz);
  2804. if(bt==markbuf) if(x>markb) x-=sz;
  2805. stbuf(markbuf);
  2806. ldbuf(bt);
  2807. fmpoint(x);
  2808. updall=1;
  2809. newy=1;
  2810. }
  2811.  
  2812. moveblk()
  2813. {
  2814. unsigned char *t;
  2815. TXTSIZ sz, x=fmnote();
  2816. struct buffer *bt=curbuf;
  2817. if(markbuf)
  2818.  {
  2819.  stbuf(curbuf);
  2820.  ldbuf(markbuf);
  2821.  }
  2822. if(marke<=markb || marke>fmsize() || !markbuf)
  2823.  {
  2824.  msg("\\iNo block\\i");
  2825.  if(markbuf)
  2826.   ldbuf(bt);
  2827.  return;
  2828.  }
  2829. if(x>=markb && x<=marke && bt==markbuf)
  2830.  {
  2831.  x=markb;
  2832.  ldbuf(bt);
  2833.  return;
  2834.  }
  2835. sz=marke-markb;
  2836. t=(unsigned char *)malloc(sz);
  2837. fmpoint(markb);
  2838. fmcpy(t,sz);
  2839. fmdel(sz);
  2840. if(bt==markbuf) if(x>markb) x-=sz, newy=1;
  2841. stbuf(markbuf); 
  2842. ldbuf(bt);
  2843. fmpoint(x);
  2844. fminss(t,sz);
  2845. free(t);
  2846. markb=x;
  2847. marke=x+sz;
  2848. markbuf=bt;
  2849. updall=1;
  2850. }
  2851.  
  2852. cpyblk()
  2853. {
  2854. unsigned char *t;
  2855. TXTSIZ x=fmnote();
  2856. struct buffer *bt=curbuf;
  2857. TXTSIZ sz;
  2858. if(markbuf)
  2859.  {
  2860.  stbuf(curbuf);
  2861.  ldbuf(markbuf);
  2862.  }
  2863. if(marke<=markb || marke>fmsize() || !markbuf)
  2864.  {
  2865.  msg("\\iNo block\\i");
  2866.  if(markbuf)
  2867.   ldbuf(bt);
  2868.  return;
  2869.  }
  2870. sz=marke-markb;
  2871. t=(unsigned char *)malloc(sz);
  2872. fmpoint(markb);
  2873. fmcpy(t,sz);
  2874. stbuf(markbuf);
  2875. ldbuf(bt); 
  2876. fmpoint(x);
  2877. fminss(t,sz);
  2878. free(t);
  2879. marke=x+sz;
  2880. markb=x;
  2881. markbuf=bt;
  2882. updall=1;
  2883. }
  2884.  
  2885. insfil()
  2886. {
  2887. unsigned char gfnam1[PATHSIZE];
  2888. unsigned char sting[PATHSIZE];
  2889. gfnam1[0]=0;
  2890. if(!getl("File to insert",gfnam1)) return;
  2891. fixpath(gfnam1);
  2892. handle=fopen(gfnam1,"r");
  2893. if(handle)
  2894.  {
  2895.  if(!fminsfil(handle))
  2896.   {
  2897.   sprintf(sting,"\\iError inserting file %s\\i",gfnam1);
  2898.   msg(sting);
  2899.   }
  2900.  newy=1;
  2901.  fclose(handle);
  2902.  }
  2903. else
  2904.  {
  2905.  sprintf(sting,"\\iError opening file %s\\i",gfnam1);
  2906.  msg(sting);
  2907.  return;
  2908.  }
  2909. }
  2910.  
  2911. push()
  2912. {
  2913. dclose();
  2914. shell();
  2915. rewrite();
  2916. }
  2917.  
  2918. suspend()
  2919. {
  2920. dclose();
  2921. susp();
  2922. rewrite();
  2923. }
  2924.  
  2925. ioverwrite() { overwrite= !overwrite; }
  2926. iwrap() { wrap= !wrap; }
  2927. iautoind() { autoind= !autoind; }
  2928. itabmagic() { tabmagic= !tabmagic; }
  2929. ipic() { pic= !pic; }
  2930. ooverwrite() { overwrite=0; }
  2931. owrap() { wrap=0; }
  2932. oautoind() { autoind=0; }
  2933. otabmagic() { tabmagic=0; }
  2934. opic() { pic=0; }
  2935.  
  2936. setrmargin()
  2937. {
  2938. unsigned char sting[80];
  2939. sprintf(sting,"%d",rmargin);
  2940. if(!getl("Right margin",sting)) return;
  2941. rmargin=atol(sting);
  2942. if(rmargin<2) rmargin=2;
  2943. }
  2944.  
  2945. mode()
  2946. {
  2947. unsigned char s[PATHSIZE];
  2948. s[0]=0;
  2949. strcat(s,"(R)ght Mrgn ");
  2950. if(overwrite) strcat(s,"(I) Overtype ");
  2951. else strcat(s,"(I)nsert ");
  2952. if(tabmagic) strcat(s,"(T)ab Magic on ");
  2953. else strcat(s,"(T)ab Magic off ");
  2954. if(wrap) strcat(s,"(W)rap on ");
  2955. else strcat(s,"(W)rap off ");
  2956. if(autoind) strcat(s,"(A) Indent on ");
  2957. else strcat(s,"(A) Indent off ");
  2958. if(pic) strcat(s,"(P)ic on: ");
  2959. else strcat(s,"(P)ic off: ");
  2960. switch(query(s))
  2961.  {
  2962.  case 'i':
  2963.  case 'I':
  2964.  case 'o':
  2965.  case 'O':
  2966.   ioverwrite();
  2967.   break;
  2968.  case 'W':
  2969.  case 'w':
  2970.   iwrap();
  2971.   break;
  2972.  case 'a':
  2973.  case 'A':
  2974.   iautoind();
  2975.   break;
  2976.  case 't':
  2977.  case 'T':
  2978.   itabmagic();
  2979.   break;
  2980.  case 'p':
  2981.  case 'P':
  2982.   ipic();
  2983.   break;
  2984.  case 'r':
  2985.  case 'R':
  2986.   setrmargin();
  2987.  }
  2988. }
  2989.  
  2990. /* Center the current line */
  2991.  
  2992. ctrlin()
  2993. {
  2994. TXTSIZ x;
  2995. int tmp=pic;
  2996. int y;
  2997. unfill();
  2998. bol();
  2999. while(y=fmrc(), y==' ' || y=='\t') fmdel(1);
  3000. eol();
  3001. x=fmnote();
  3002. bol();
  3003. if(x-fmnote()>rmargin) return;
  3004. y=(rmargin/2)-(x-fmnote())/2;
  3005. while(y--) fminsc(' ');
  3006. pic=1;
  3007. udnarw();
  3008. pic=tmp;
  3009. }
  3010.  
  3011. /* Reformat a paragraph */
  3012.  
  3013. reformat()
  3014. {
  3015. TXTSIZ tmp,idt,idt1,b,e,cur,ncur= -1;
  3016. unsigned char ch;
  3017.  
  3018. cur=fmnote();        /* Save cursor position */
  3019.  
  3020. /* First, determine indentation on current or first non-blank line */
  3021.  
  3022. up:
  3023. idt=calcs();
  3024. if(fmeof()) return;     /* Not if at end of file */
  3025. if(fmrc()==NL)  /* Ignore any blank lines */
  3026.  {
  3027.  dnarw();
  3028.  goto up;
  3029.  }
  3030. bol();
  3031.  
  3032. /* Now find beginning of paragraph */
  3033. /* It will be indicated by a change of indentation or a blank line or bof */
  3034.  
  3035. while(fmnote())         /* Beginning is at bof */
  3036.  {
  3037.  uparw();
  3038.  idt1=calcs();
  3039.  if(fmrc()==NL) /* Beginning is blank line */
  3040.   {
  3041.   bol();
  3042.   dnarw();
  3043.   break;
  3044.   }
  3045.  bol();
  3046.  if(idt1>idt) break;
  3047.  if(idt1<idt)
  3048.   {
  3049.   dnarw();
  3050.   break;
  3051.   }
  3052.  }
  3053.  
  3054. /* Point is now at beginning of paragraph (hopefully) */
  3055. /* Set the mark */
  3056.  
  3057. b=fmnote();
  3058.  
  3059. idt=calcs(); bol();    /* Save indentation level of first line of paragraph */
  3060.  
  3061. /* Now move to after end of paragraph */
  3062. while(1)
  3063.  {
  3064.  tmp=fmnote();
  3065.  dnarw();
  3066.  if(fmnote()==tmp)      /* Paragraph ends on end of file */
  3067.   {
  3068.   eol();
  3069.   fminsc(NL);        /* Stick in a NL */
  3070.   fmgetc();
  3071.   extend=0;        /* I don't think I have to do this but... */
  3072.   break;
  3073.   }
  3074.  idt1=calcs();
  3075.  if(fmrc()==NL)        /* Paragraph ends on blank line */
  3076.   {
  3077.   bol();
  3078.   break;
  3079.   }
  3080.  bol();
  3081.  if(idt1>idt) break;    /* Paragraph ends when indentation increases */
  3082.  }
  3083.  
  3084. /* Point now after end of paragraph, cut paragraph */
  3085. e=fmnote();
  3086.  
  3087. /* Now reinsert paragraph in a nice way */
  3088.  
  3089. if(e>b)
  3090.  {
  3091.  unsigned oldwrap=wrap;
  3092.  unsigned oldoverwrite=overwrite;
  3093.  unsigned oldauto=autoind;
  3094.  unsigned flag=0;
  3095.  unsigned char ccc=0;
  3096.  TXTSIZ ppp=b; 
  3097.  undoflag=0;
  3098.  overwrite=0;
  3099.  wrap=1;
  3100.  while(ppp!=e)
  3101.   {
  3102.   tmp=fmnote();
  3103.   fmpoint(ppp);
  3104.   if(ppp>=cur && ncur== -1) ncur=tmp;
  3105.   ppp++;
  3106.   ch=fmrc();
  3107.   fmpoint(tmp);
  3108.   if(ch==NL) ch=' ';
  3109.   if(ch==' ' || ch==TAB)
  3110.    {
  3111.    if(flag==0) itype(ch);
  3112.    else if(flag==1 && ch!='\t')
  3113.      {
  3114.      itype(' ');
  3115.      if(!(ccc=='.' || ccc==':' || ccc=='?' || ccc=='!' || ccc=='\"' ||
  3116.           ccc==';')) flag=2;
  3117.      }
  3118.    else if(ch=='\t') itype('\t');
  3119.    }
  3120.   else
  3121.    {
  3122.    flag=1;
  3123.    itype(ch);
  3124.    }
  3125.   ccc=ch;
  3126.   }
  3127.  autoind=0;
  3128.  if(flag) itype(NL);
  3129.  /* Make undo record for entered paragraph */
  3130.   {
  3131.   /* New record */
  3132.   struct undorec *it=(struct undorec *)malloc(sizeof(struct undorec));
  3133.   if(redorecs) killredo();
  3134.   it->next=undorecs;
  3135.   undorecs=it;
  3136.   it->size=fmnote()-e;
  3137.   it->where=e;
  3138.   it->buffer=0;
  3139.   ++nundorecs;
  3140.   if(nundorecs==20)
  3141.    {
  3142.    struct undorec *p;
  3143.    for(it=undorecs;it->next;p=it,it=it->next);
  3144.    if(it->buffer) free(it->buffer);
  3145.    free(it);
  3146.    p->next=0;
  3147.    }
  3148.   }
  3149.  
  3150.  undoflag=1;
  3151.  wrap=oldwrap;
  3152.  overwrite=oldoverwrite;
  3153.  autoind=oldauto;
  3154.  fmpoint(b);
  3155.  fmdel(e-b);
  3156.  fmpoint(ncur-(e-b));
  3157.  newy=1;
  3158.  }
  3159. }
  3160.  
  3161. killword()
  3162. {
  3163. unsigned char ch;
  3164. ch=fmrc();
  3165. if(((ch>='a' && ch<='z') || (ch>='A' && ch <='Z')) && !fmeof())
  3166.  do
  3167.   {
  3168.   delch();
  3169.   ch=fmrc();
  3170.   } while (((ch>='a' && ch<='z') || (ch>='A' && ch <='Z')) && !fmeof());
  3171. else
  3172.  if((ch==' ' || ch==TAB || ch==NL) && !fmeof())
  3173.   do
  3174.    {
  3175.    delch();
  3176.    ch=fmrc();
  3177.    } while (!fmeof() && (ch==' ' || ch==NL || ch==TAB));
  3178. else
  3179.  if(ch>='0' && ch<='9' && !fmeof())
  3180.   do
  3181.    {
  3182.    delch();
  3183.    ch=fmrc();
  3184.    } while (!fmeof() && ch>='0' && ch<='9');
  3185. else delch();
  3186. }
  3187.  
  3188. backword()
  3189. {
  3190. unsigned char ch;
  3191. if(fmnote())
  3192.  {
  3193.  fmpoint(fmnote()-1);
  3194.  ch=fmgetc();
  3195.  if((ch>='a' && ch<='z') || (ch>='A' && ch <='Z'))
  3196.   {
  3197. up:
  3198.   backs();
  3199.   if(fmnote())
  3200.    {
  3201.    fmpoint(fmnote()-1);
  3202.    ch=fmrc();
  3203.    fmgetc();
  3204.    if((ch>='a' && ch<='z') || (ch>='A' && ch <='Z')) goto up;
  3205.    }
  3206.   }
  3207.  else if(ch==' ' || ch==TAB || ch==NL)
  3208.    {
  3209. up1:
  3210.    backs();
  3211.    if(fmnote())
  3212.     {
  3213.     fmpoint(fmnote()-1);
  3214.     ch=fmrc();
  3215.     fmgetc();
  3216.     if(ch==' ' || ch==TAB || ch==NL) goto up1;
  3217.     }
  3218.    }
  3219.  else if(ch>='0' && ch<='9')
  3220.    {
  3221. up2:
  3222.    backs();
  3223.    if(fmnote())
  3224.     {
  3225.     fmpoint(fmnote()-1);
  3226.     ch=fmrc();
  3227.     fmgetc();
  3228.     if(ch>='0' && ch<='9') goto up2;
  3229.     }
  3230.    }
  3231.  else backs();
  3232.  }
  3233. }
  3234.  
  3235. word()
  3236. {
  3237. int c;
  3238. if(fmnote()==fmsize()) return 0;
  3239. c=fmrc();
  3240. if(c>='a' && c<='z') return 1;
  3241. if(c>='A' && c<='Z') return 1;
  3242. if(c>='0' && c<='9') return 1;
  3243. return 0;
  3244. }
  3245.  
  3246. wrdl()
  3247. {
  3248. extend=0;
  3249. newy=1;
  3250. if(!fmnote()) return;
  3251. fmrgetc();
  3252. while(!word())
  3253.  {
  3254.  if(!fmnote()) return;
  3255.  fmrgetc();
  3256.  }
  3257. while(word())
  3258.  {
  3259.  if(!fmnote()) return;
  3260.  fmrgetc();
  3261.  }
  3262. fmgetc();
  3263. }
  3264.  
  3265. wrdr()
  3266. {
  3267. extend=0;
  3268. newy=1;
  3269. while(!word())
  3270.  {
  3271.  if(fmnote()==fmsize()) return;
  3272.  fmgetc();
  3273.  }
  3274. while(word())
  3275.  {
  3276.  if(fmnote()==fmsize()) return;
  3277.  fmgetc();
  3278.  }
  3279. }
  3280.  
  3281. unsigned char lft[]="{[(<`";
  3282. unsigned char rht[]="}])>'";
  3283.  
  3284. gotomatching()
  3285. {
  3286. TXTSIZ cur=fmnote(),cnt;
  3287. unsigned char c;
  3288. int x;
  3289. extend=0;
  3290. if(fmeof()) return;
  3291. c=fmrc();
  3292. for(x=0;x!=strlen(lft);++x)
  3293.  if(lft[x]==c)
  3294.   {
  3295.   cnt=0;
  3296.   while(!fmeof())
  3297.    {
  3298.    c=fmgetc();
  3299.    if(lft[x]==c) ++cnt;
  3300.    if(rht[x]==c)
  3301.     if(!--cnt)
  3302.      {
  3303.      newy=1;
  3304.      fmrgetc();
  3305.      return;
  3306.      }
  3307.    }
  3308.   fmpoint(cur);
  3309.   return;
  3310.   }
  3311.  else if(rht[x]==c)
  3312.   {
  3313.   cnt=1;
  3314.   while(fmnote())
  3315.    {
  3316.    c=fmrgetc();
  3317.    if(rht[x]==c) ++cnt;
  3318.    if(lft[x]==c)
  3319.     if(!--cnt)
  3320.      {
  3321.      newy=1;
  3322.      return;
  3323.      }
  3324.    }
  3325.   fmpoint(cur);
  3326.   return;
  3327.   }
  3328. }
  3329.  
  3330. int setindent()
  3331. {
  3332. TXTSIZ idt,idt1,cur=fmnote(),tmp;
  3333. if(curbuf==markbuf && cur>=markb && cur<marke) return 1;
  3334. markbuf=curbuf; markb=0; marke=0;
  3335. /* Find beginning */
  3336. idt=calcs();
  3337. if(fmeof()) goto done;
  3338. if(fmrc()==NL) goto done;
  3339. while(fmnrnl())
  3340.  {
  3341.  idt1=calcs();
  3342. /* if(fmrc()!=NL) if(idt1<idt) Use this line instead of one below for
  3343.    setindent to ignore blank lines */
  3344.  if(fmrc()==NL || idt1<idt)
  3345.   {
  3346.   if(fmfnl()) fmgetc();
  3347.   break;
  3348.   }
  3349.  }
  3350. /* Point is now at beginning of block (hopefully) */
  3351. /* Set the mark */
  3352. markb=fmnote();
  3353.  
  3354. while(fmfnl())
  3355.  {
  3356.  fmgetc();
  3357.  idt1=calcs();
  3358. /* if(fmrc()!=NL) if(idt1<idt) Use this line instead of one below for
  3359.    setindent to ignore blank lines */
  3360.  if(fmrc()==NL || idt1<idt)
  3361.   {
  3362.   bol();
  3363.   break;
  3364.   }
  3365.  }
  3366. marke=fmnote();
  3367. done: fmpoint(cur);
  3368. return 0;
  3369.  
  3370. indentr()
  3371. {
  3372. TXTSIZ cur=fmnote(),tmp;
  3373. if(!setindent()) return;
  3374. fmpoint(markb);
  3375. while(fmnote()<marke)
  3376.  {
  3377.  calcs();
  3378.  if(fmeof()) break;
  3379.  if(fmrc()!=NL)
  3380.   {
  3381.   if(fmnote()<=cur) ++cur;
  3382.   fminsc(' ');
  3383.   }
  3384.  if(fmfnl()) fmgetc();
  3385.  else break;
  3386.  }
  3387. done: fmpoint(cur);
  3388. return;
  3389. }
  3390.  
  3391. indentl()
  3392. {
  3393. TXTSIZ cur=fmnote(),idt,tmp;
  3394. if(!setindent()) return;
  3395. fmpoint(markb);
  3396. while(fmnote()<marke)
  3397.  {
  3398.  idt=calcs();
  3399.  if(fmeof()) break;
  3400.  if(fmrc()!=NL) if(!idt) goto done;
  3401.  if(fmfnl()) fmgetc();
  3402.  else break;
  3403.  }
  3404. fmpoint(markb);
  3405. while(fmnote()<marke)
  3406.  {
  3407.  calcs();
  3408.  if(fmeof()) break;
  3409.  if(fmrc()!=NL)
  3410.   {
  3411.   if(fmnote()<=cur) --cur;
  3412.   fmrgetc();
  3413.   fmdel(1);
  3414.   }
  3415.  if(fmfnl()) fmgetc();
  3416.  else break;
  3417.  }
  3418. done: fmpoint(cur);
  3419. return;
  3420. }
  3421.  
  3422. struct window *curwin;
  3423. struct buffer *curbuf;
  3424. struct window *topwin;
  3425.  
  3426. ldbuf(zuffer)
  3427. struct buffer *zuffer;
  3428. {
  3429. if(zuffer==curbuf) return;
  3430. curbuf=zuffer;
  3431. backup=zuffer->backup;
  3432. strcpy(gfnam,zuffer->gfnam);
  3433. bufsiz=zuffer->bufsiz;
  3434. buffer=zuffer->buf;
  3435. filend=zuffer->filend;
  3436. hole=zuffer->hole;
  3437. ehole=zuffer->ehole;
  3438. changed=zuffer->changed;
  3439. undorecs=zuffer->undorecs;
  3440. nundorecs=zuffer->nundorecs;
  3441. redorecs=zuffer->redorecs;
  3442. undoptr=0;
  3443. }
  3444.  
  3445. ldbuf1(zuffer)
  3446. struct buffer *zuffer;
  3447. {
  3448. curbuf=zuffer;
  3449. backup=zuffer->backup;
  3450. strcpy(gfnam,zuffer->gfnam);
  3451. bufsiz=zuffer->bufsiz;
  3452. buffer=zuffer->buf;
  3453. filend=zuffer->filend;
  3454. hole=zuffer->hole;
  3455. ehole=zuffer->ehole;
  3456. changed=zuffer->changed;
  3457. undorecs=zuffer->undorecs;
  3458. redorecs=zuffer->redorecs;
  3459. nundorecs=zuffer->nundorecs;
  3460. undoptr=0;
  3461. }
  3462.  
  3463. stbuf(zuffer)
  3464. struct buffer *zuffer;
  3465. {
  3466. zuffer->backup=backup;
  3467. strcpy(zuffer->gfnam,gfnam);
  3468. zuffer->bufsiz=bufsiz;
  3469. zuffer->buf=buffer;
  3470. zuffer->filend=filend;
  3471. zuffer->hole=hole;
  3472. zuffer->ehole=ehole;
  3473. zuffer->changed=changed;
  3474. zuffer->undorecs=undorecs;
  3475. zuffer->nundorecs=nundorecs;
  3476. zuffer->redorecs=redorecs;
  3477. undoptr=0;
  3478. }
  3479.  
  3480. ldwin(window)
  3481. struct window *window;
  3482. {
  3483. saddr=window->saddr;
  3484. xoffset=window->xoffset;
  3485. pic=window->pic;
  3486. autoind=window->autoind;
  3487. overwrite=window->overwrite;
  3488. wrap=window->wrap;
  3489. tabmagic=window->tabmagic;
  3490. rmargin=window->rmargin;
  3491. extend=window->extend;
  3492. ldbuf1(window->buffer);
  3493. fmpoint(window->cursor);
  3494. }
  3495.                                    
  3496. stwin(window)
  3497. struct window *window;
  3498. window->saddr=saddr;
  3499. window->xoffset=xoffset;
  3500. window->pic=pic;
  3501. window->autoind=autoind;
  3502. window->overwrite=overwrite;
  3503. window->wrap=wrap;
  3504. window->tabmagic=tabmagic;
  3505. window->rmargin=rmargin;
  3506. window->extend=extend;
  3507. window->cursor=fmnote();
  3508. stbuf(window->buffer);
  3509. }
  3510.  
  3511. wfit()
  3512. {
  3513. struct window *x;
  3514. int total;
  3515. updall=1;
  3516. newy=1;
  3517. up:
  3518. total=height-wind;
  3519. for(x=topwin;1;x=x->next)
  3520.  {
  3521.  if(x->height<3) x->height=3;
  3522.  if(curwin==x && total>=3) break;
  3523.  if(total<3) goto in;
  3524.  total-=x->height;
  3525.  if(total<0)
  3526.   {
  3527.   in:
  3528.   topwin=topwin->next;
  3529.   goto up;
  3530.   }
  3531.  }
  3532. for(x=topwin,total=wind;1;x=x->next)
  3533.  {
  3534.  x->wind=total;
  3535.  if(x->height<3) x->height=3;
  3536.  total+=x->height;
  3537.  if(total>=height || x->next==topwin)
  3538.   {
  3539.   total-=x->height;
  3540.   x->height=height-total;
  3541.   return;
  3542.   }
  3543.  }
  3544. }
  3545.  
  3546. wnext()
  3547. {
  3548. stwin(curwin);
  3549. curwin=curwin->next;
  3550. ldwin(curwin);
  3551. wfit();
  3552. }
  3553.  
  3554. wprev()
  3555. {
  3556. stwin(curwin);
  3557. curwin=curwin->prev;
  3558. ldwin(curwin);
  3559. wfit();
  3560. }
  3561.  
  3562. wexplode()
  3563. {
  3564. struct window *x;
  3565. int y;
  3566. if(curwin->height!=height-wind)
  3567.  { /* Make curwin only */
  3568.  topwin=curwin;
  3569.  x=topwin;
  3570.  do
  3571.   {
  3572.   x->height=height-wind;
  3573.   x->wind=wind;
  3574.   x=x->next;
  3575.   }
  3576.   while(x!=topwin);
  3577.  newy=1;
  3578.  }
  3579. else
  3580.  { /* Show all windows */
  3581.  x=topwin; y=0;
  3582.  do y++, x=x->next; while(x!=topwin);
  3583.  if((height-wind)/y<3) y=3;
  3584.  else y=(height-wind)/y;
  3585.  x=topwin;
  3586.  do x->height=y, x=x->next; while(x!=topwin);
  3587.  wfit();
  3588.  }
  3589. }
  3590.  
  3591. wgrow()
  3592. {
  3593. if(curwin->wind+curwin->height==height)
  3594.  {
  3595.  if(curwin->wind!=wind) if(curwin->prev->height>3)
  3596.   curwin->prev->height--, curwin->height++, curwin->wind--, updall=1;
  3597.  }
  3598. else
  3599.  {
  3600.  if(curwin->next->height>3)
  3601.   curwin->height++, curwin->next->wind++, curwin->next->height--, updall=1;
  3602.  }
  3603. newy=1;
  3604. }
  3605.  
  3606. wshrink()
  3607. {
  3608. if(curwin->wind+curwin->height==height)
  3609.  {
  3610.  if(curwin->wind!=wind) if(curwin->height>3)
  3611.  curwin->height--, curwin->prev->height++, curwin->wind++, updall=1;
  3612.  }
  3613. else
  3614.  {
  3615.  if(curwin->height>3)
  3616.  curwin->height--, curwin->next->wind--, curwin->next->height++, updall=1;
  3617.  }
  3618. newy=1;
  3619. }
  3620.  
  3621. wsplit()
  3622. {
  3623. struct window *new;
  3624. if(curwin->height<6) return;
  3625. new=(struct window *)malloc(sizeof(struct window));
  3626. new->buffer=curbuf;
  3627. stwin(new);
  3628. new->next=curwin->next;
  3629. new->prev=curwin;
  3630. curwin->next->prev=new;
  3631. curwin->next=new;
  3632. if(curwin->height&1)
  3633.  {
  3634.  curwin->height/=2;
  3635.  new->height=curwin->height+1;
  3636.  }
  3637. else
  3638.  {
  3639.  curwin->height/=2;
  3640.  new->height=curwin->height;
  3641.  }
  3642. if(curwin->hheight&1)
  3643.  {
  3644.  curwin->hheight/=2;
  3645.  new->hheight=curwin->hheight+1;
  3646.  }
  3647. else
  3648.  {
  3649.  curwin->hheight/=2;
  3650.  new->hheight=curwin->hheight;
  3651.  }
  3652. new->wind=curwin->wind+curwin->height;
  3653. curwin=new;
  3654. curbuf->count++;
  3655. updall=1;
  3656. newy=1;
  3657. }
  3658.  
  3659. wedit()
  3660. {
  3661. unsigned char gfnam1[PATHSIZE];
  3662. unsigned char sting[PATHSIZE];
  3663. int c;
  3664. struct window *x;
  3665. stwin(curwin);
  3666. if(curbuf->count==1 && curbuf->changed)
  3667.  {
  3668.  c=askyn("Do you really want to throw away this file?"); 
  3669.  if(c=='N') return;
  3670.  if(c== -1) return;
  3671.  }
  3672. gfnam1[0]=0;
  3673. if(!getl("File to edit",gfnam1)) return;
  3674. fixpath(gfnam1);
  3675. x=topwin;
  3676. do
  3677.  {
  3678.  if(!strcmp(gfnam1,x->buffer->gfnam))
  3679.   {
  3680.   if(curbuf->count==1)
  3681.    {
  3682.    killredo();
  3683.    killundo();
  3684.    free(curbuf->buf), free(curbuf);
  3685.    if(curbuf==markbuf) markbuf=0;
  3686.    }                           
  3687.   else 
  3688.    curbuf->count--;
  3689.   curwin->buffer=x->buffer;
  3690.   curwin->buffer->count++;
  3691.   ldbuf(x->buffer);
  3692.   bof();
  3693.   return;
  3694.   }
  3695.  x=x->next;
  3696.  }
  3697.  while(x!=topwin);
  3698. strcpy(gfnam,gfnam1);
  3699. stmode(gfnam);
  3700. if(curbuf->count==1) free(curbuf->buf),
  3701.                              free(curbuf);
  3702. else curbuf->count--;
  3703. curwin->buffer=(struct buffer *)malloc(sizeof(struct buffer));
  3704. curbuf=curwin->buffer;
  3705. curbuf->count=1;
  3706. fmopen();
  3707. bof();
  3708. handle=fopen(gfnam1,"r");
  3709. if(handle)
  3710.  {
  3711.  if(!fminsfil(handle))
  3712.   {
  3713.   sprintf(sting,"\\iError loading file %s\\i",gfnam1);
  3714.   msg(sting);
  3715.   }
  3716.  changed=0;
  3717.  newy=1;
  3718.  fclose(handle);
  3719.  }
  3720. else
  3721.  {
  3722.  newy=1;
  3723.  upd=1;
  3724.  if(errno==ENOENT)
  3725.   {
  3726.   dupdate();
  3727.   msgout(curwin->wind+1,"New File",0,0);
  3728.   cpos(curwin->wind+1,0);
  3729.   backup=1;
  3730.   }
  3731.  else
  3732.   {
  3733.   dupdate();
  3734.   msgout(curwin->wind+1,"\\iError opening file\\i",0,1);
  3735.   cpos(curwin->wind+1,0);
  3736.   }
  3737.  noupdate=1;
  3738.  return;
  3739.  }
  3740. }
  3741.  
  3742. rtn()
  3743. {
  3744. type(NL);
  3745. }
  3746.  
  3747. stquote()
  3748. {
  3749. quoteflg=1;
  3750. }
  3751.  
  3752. stquote8th()
  3753. {
  3754. quote8th=1;
  3755. }
  3756.  
  3757. CMD kkm[73]=
  3758. {
  3759.  {"uparw",0,uuparw},
  3760.  {"rtarw",0,urtarw},
  3761.  {"ltarw",0,ultarw},
  3762.  {"dnarw",0,udnarw},
  3763.  {"eol",0,eol},
  3764.  {"pgdn",0,pgdn},
  3765.  {"bol",0,bol},
  3766.  {"pgup",0,pgup},
  3767.  {"ctrlin",0,ctrlin},
  3768.  {"setbeg",0,setbeg},
  3769.  {"cpyblk",0,cpyblk},
  3770.  {"saveit",0,saveit},
  3771.  {"wedit",0,wedit},
  3772.  {"findfirst",0,findfirst},
  3773.  {"findnext",0,findnext},
  3774.  {"wgrow",0,wgrow},
  3775.  {"thelp",0,thelp},
  3776.  {"wexplode",0,wexplode},
  3777.  {"reformat",0,reformat},
  3778.  {"setend",0,setend},
  3779.  {"findline",0,findline},
  3780.  {"moveblk",0,moveblk},
  3781.  {"wnext",0,wnext},
  3782.  {"wprev",0,wprev},
  3783.  {"wsplit",0,wsplit},
  3784.  {"insfil",0,insfil},
  3785.  {"wshrink",0,wshrink},
  3786.  {"bof",0,bof},
  3787.  {"eof",0,eof},
  3788.  {"writeblk",0,writeblk},
  3789.  {"exsave",0,exsave},
  3790.  {"delblk",0,delblk},
  3791.  {"push",0,push},
  3792.  {"suspend",0,suspend},
  3793.  {"eexit",0,eexit},
  3794.  {"delch",0,delch},
  3795.  {"inss",0,inss},
  3796.  {"backs",0,backs},
  3797.  {"type",0,type},
  3798.  {"rtn",0,rtn},
  3799.  {"backword",0,backword},
  3800.  {"rewrite",0,rewrite},
  3801.  {"mode",0,mode},
  3802.  {"killword",0,killword},
  3803.  {"wrdr",0,wrdr},
  3804.  {"dellin",0,dellin},
  3805.  {"wrdl",0,wrdl},
  3806.  {"stquote8th",0,stquote8th},
  3807.  {"stquote",0,stquote},
  3808.  {"gotomatching",0,gotomatching},
  3809.  {"indentl",0,indentl},
  3810.  {"indentr",0,indentr},
  3811.  {"undo",0,undo},
  3812.  {"redo",0,redo},
  3813.  {"killlin",0,killlin},
  3814.  {"deleol",0,deleol},
  3815.  {"ioverwrite",0,ioverwrite},
  3816.  {"iwrap",0,iwrap},
  3817.  {"iautoind",0,iautoind},
  3818.  {"itabmagic",0,itabmagic},
  3819.  {"ipic",0,ipic},
  3820.  {"ooverwrite",0,ooverwrite},
  3821.  {"owrap",0,owrap},
  3822.  {"oautoind",0,oautoind},
  3823.  {"otabmagic",0,otabmagic},
  3824.  {"opic",0,ipic},
  3825.  {"setrnargin",0,setrmargin},
  3826.  {"cmdblk",0,cmdblk},
  3827.  {"repeat",0,repeat},
  3828.  {"macrob",0,macrob},
  3829.  {"macroe",0,macroe},
  3830.  {"macrodo",0,macrodo},
  3831.  {"wait",0,waite}
  3832.  };
  3833.  
  3834. CONTEXT km={0, "main", 0, 73, kkm};
  3835.  
  3836. /** Key sequence processing functions **/
  3837.  
  3838. struct kmap *curmap;
  3839. int quoteflg=0;
  3840. int quote8th=0;
  3841.  
  3842. int record=0;
  3843. unsigned char *kmacro=0;
  3844. int kmacrox=0;
  3845. int kmacrosz=0;
  3846.  
  3847. int macroadd(c)
  3848. unsigned char c;
  3849. {
  3850. if(kmacrox+3>=kmacrosz) 
  3851.  if(kmacro) kmacro=(unsigned char *)realloc(kmacro,kmacrosz+=10);
  3852.  else kmacro=(unsigned char *)malloc(kmacrosz=10);
  3853. if(c=='\\')
  3854.  {
  3855.  kmacro[kmacrox++]='\\';
  3856.  kmacro[kmacrox++]='\\';
  3857.  }
  3858. else
  3859.  kmacro[kmacrox++]=c;
  3860. kmacro[kmacrox]=0;
  3861. }
  3862.  
  3863. macrob()
  3864. {
  3865. kmacrox=0;
  3866. record=1;
  3867. }
  3868.  
  3869. macroe()
  3870. {
  3871. record=0;
  3872. }
  3873.  
  3874. macrodo()
  3875. {
  3876. int z=repeatamnt;
  3877. if(record) return;
  3878. repeatamnt=1;
  3879. nrepeatamnt=1;
  3880. take=kmacro;
  3881. waite();
  3882. repeatamnt=z;
  3883. }
  3884.  
  3885. int *runfuncs;
  3886. int rsize=0;
  3887. int rptr=0;
  3888.  
  3889. isrunning(r,n)
  3890. {
  3891. int z;
  3892. for(z=0;z!=rptr;z+=2) if(r==runfuncs[z] && n==runfuncs[z+1]) return 1;
  3893. return 0;
  3894. }
  3895.  
  3896. pop() { rptr-=2; } 
  3897.  
  3898. running(r,n)
  3899. {
  3900. if(rsize==rptr)
  3901.  if(rsize) runfuncs=(int *)realloc(runfuncs,sizeof(int)*(rsize+=10));
  3902.  else runfuncs=(int *)malloc(sizeof(int)*(rsize=10));
  3903. runfuncs[rptr++]=r;
  3904. runfuncs[rptr++]=n;
  3905. }
  3906.  
  3907. int dokey(k)
  3908. unsigned char k;
  3909. {
  3910. int above=curmap->len;
  3911. int below=0;
  3912. int new;
  3913. struct kmap *r;
  3914. if(quoteflg)
  3915.  {
  3916.  quoteflg=0;
  3917.  if(k>='@' && k<='_') k-='@';
  3918.  if(k>='a' && k<='z') k-='`';
  3919.  if(k=='?') k=127;
  3920.  type(k);
  3921.  goto abcd;
  3922.  }
  3923. goto in;
  3924. do
  3925.  {
  3926.  new=(above+below)/2;
  3927.  if((curmap->keys[new].k&KEYMASK)==k)
  3928.   if(curmap->keys[new].k&KEYSUB)
  3929.    {
  3930.    curmap=(KMAP *)(curmap->keys[new].n);
  3931.    return Kaccept;
  3932.    }
  3933.   else
  3934.    {
  3935.    int h=height, w=width, zz, rpt=repeatamnt;
  3936.    getsize();
  3937.    if(h!=height || w!=width) resize();
  3938.    r=curmap;
  3939.    curmap=km.kmap;
  3940.    nrepeatamnt=1;
  3941.    while(rpt--)
  3942.     {
  3943.     if(rpt>1 && have)
  3944.      {
  3945.      anext();
  3946.      msg("Repeat aborted");
  3947.      undoptr=0;
  3948.      break;
  3949.      }
  3950.     if(isrunning(r,new)) undoptr=0, type(k);
  3951.     else
  3952.      {
  3953.      running(r,new);
  3954.      for(zz=0;r->keys[new].n[zz]!= -1;zz+=2)
  3955.       {
  3956.       if(r->keys[new].n[zz])
  3957.        {
  3958.        take=(unsigned char *)r->keys[new].n[zz+1];
  3959.        }
  3960.       else
  3961.        {
  3962.        if(km.cmd[r->keys[new].n[zz+1]].func!=redo &&
  3963.           km.cmd[r->keys[new].n[zz+1]].func!=undo) undoptr=0;
  3964.        km.cmd[r->keys[new].n[zz+1]].func(k);
  3965.        if(leave) goto abcd;
  3966.        }
  3967.       }
  3968.      pop();
  3969.      }
  3970.     }
  3971.    abcd:
  3972.    repeatamnt=nrepeatamnt;
  3973.    if(!leave)
  3974.     {
  3975.     if(!uuu) upd=1;
  3976.     else uuu=0;
  3977.     if(!noupdate) dupdate();
  3978.     else noupdate=0;
  3979.     }
  3980.    return 0;
  3981.    }
  3982.  else if((curmap->keys[new].k&KEYMASK)>k)
  3983.   {
  3984.   above=new;
  3985.   in:
  3986.   if(above==below) break;
  3987.   }
  3988.  else if(below==new) break;
  3989.  else below=new;
  3990.  } while(1);
  3991. curmap=km.kmap;
  3992. return Kbad;
  3993. }
  3994.  
  3995. edit()
  3996. {
  3997. newy=1;
  3998. dupdate();
  3999. imsg();
  4000. dokey(anext());
  4001. if(leave) return;
  4002. upd=1;
  4003. newy=1;
  4004. do
  4005.  dokey(anext());
  4006.  while(!leave);
  4007. }
  4008.  
  4009. int waite()
  4010. {
  4011. while(take && *take)
  4012.  {
  4013.  dokey(anext());
  4014.  if(leave) break;
  4015.  }
  4016. }
  4017.  
  4018. struct mpair
  4019.  {
  4020.  struct mpair *next;
  4021.  unsigned char *s;
  4022.  int wrap;
  4023.  int autoind;
  4024.  int pic;
  4025.  int overwrite;
  4026.  int tabmagic;
  4027.  TXTSIZ rmargin;
  4028.  };
  4029.  
  4030. struct mpair *mpairs=0;
  4031.  
  4032. stmode(name)
  4033. unsigned char *name;
  4034. {
  4035. int x=strlen(name);
  4036. struct mpair *mp=mpairs;
  4037. while(mp)
  4038.  if(!strcmp(mp->s,name+x-strlen(mp->s)))
  4039.   {
  4040.   autoind=mp->autoind;
  4041.   wrap=mp->wrap;
  4042.   overwrite=mp->overwrite;
  4043.   pic=mp->pic;
  4044.   tabmagic=mp->tabmagic;
  4045.   rmargin=mp->rmargin;
  4046.   break;
  4047.   }
  4048.  else mp=mp->next;
  4049. }
  4050.  
  4051. int process(name,cmds)
  4052. unsigned char *name;
  4053. CONTEXT *cmds;
  4054. {
  4055. CONTEXT *context=0;
  4056. unsigned char buf[PATHSIZE];
  4057. KMAP *kmap;
  4058. FILE *fd=fopen(name,"r");
  4059. int x,y,n,z,macrox,macrosize,*macro,macroc;
  4060. if(!fd) return -1;
  4061. printf("Processing keymap file %s ...",name);
  4062. fflush(stdout);
  4063. while(fgets(buf,256,fd))
  4064.  {
  4065.  if(buf[0]=='{')
  4066.   {
  4067.   up:
  4068.   if(!fgets(buf,256,fd)) break;
  4069.   if(buf[0]=='}') continue;
  4070.   if(helpsize+strlen(buf)>helpblksize)
  4071.    {
  4072.    if(help) help=(unsigned char *)realloc(help,helpblksize+strlen(buf)+320);
  4073.    else help=(unsigned char *)malloc(strlen(buf)+320);
  4074.    helpblksize+=strlen(buf)+320;
  4075.    }
  4076.   strcat(help,buf);
  4077.   helpsize=strlen(help);
  4078.   ++helplines;
  4079.   goto up;
  4080.   }
  4081.  if(buf[0]=='*')
  4082.   {
  4083.   struct mpair *mp=(struct mpair *)calloc(sizeof(struct mpair),1);
  4084.   int c=0;
  4085.   mp->next=mpairs;
  4086.   mp->rmargin=76;
  4087.   mpairs=mp;
  4088.   for(x=0;buf[x];x++)
  4089.    if(buf[x]==' ' || buf[x]=='\t' || buf[x]=='\n')
  4090.     {
  4091.     c=buf[x];
  4092.     buf[x]=0;
  4093.     break;
  4094.     }
  4095.   mp->s=strdupp(buf+1);
  4096.   buf[x]=c;
  4097.   while(buf[x])
  4098.    if(buf[x]!=' ' && buf[x]!='\t' && buf[x]!='\n') break;
  4099.    else x++;
  4100.   while(buf[x] && buf[x]!=' ' && buf[x]!='\t' && buf[x]!='\n')
  4101.    {
  4102.    switch(buf[x])
  4103.     {
  4104.    case 'O':
  4105.    case 'o': mp->overwrite=1;
  4106.    break;
  4107.    case 'W':
  4108.    case 'w': mp->wrap=1;
  4109.    break;
  4110.    case 'a':
  4111.    case 'A': mp->autoind=1;
  4112.    break;
  4113.    case 'p':
  4114.    case 'P': mp->pic=1;
  4115.    break;
  4116.    case '0': case '1': case '2': case '3': case '4': case '5': case '6':
  4117.    case '7': case '8': case '9':
  4118.    mp->rmargin=buf[x++]-'0';
  4119.    while(buf[x]>='0' && buf[x]<='9') mp->rmargin=mp->rmargin*10+buf[x++]-'0';
  4120.    --x;
  4121.    break;
  4122.    case 't':
  4123.    case 'T': mp->tabmagic=1;
  4124.     }
  4125.    x++;
  4126.    }
  4127.   continue;
  4128.   }
  4129.  if(buf[0]==':' && buf[1]!=' ' && buf[1]!='\t')
  4130.   {
  4131.   for(x=0;buf[x];x++)
  4132.    if(buf[x]==' ' || buf[x]=='\t' || buf[x]=='\n')
  4133.     {
  4134.     buf[x]=0;
  4135.     break;
  4136.     }
  4137.   context=cmds;
  4138.   while(strcmp(buf+1,context->name))
  4139.    {
  4140.    context=context->next;
  4141.    if(!context)
  4142.     {
  4143.     printf("Unknown context name in keyboard file\n");
  4144.     return -1;
  4145.     }
  4146.    }
  4147.   continue;
  4148.   }
  4149.  for(x=0;buf[x];x++) if(buf[x]==' ' || buf[x]=='\t' || buf[x]=='\n' ||
  4150.                         buf[x]==',') break;
  4151.  if(buf[0]==' ' || buf[0]=='\t' || buf[0]=='\n' || !buf[x]) continue;
  4152.  if(!context)
  4153.   {
  4154.   printf("No context selected for key\n");
  4155.   return -1;
  4156.   }
  4157.  if(buf[0]=='\"')
  4158.   {
  4159.   int q;
  4160.   x=0;
  4161.   for(q= ++x;buf[q];++q)
  4162.    if(buf[q]=='\"' && buf[q-1]!='\\' || buf[q]=='\n') break;
  4163.   macroc=buf[q]; buf[q]=0;
  4164.   macro=(int *)malloc(sizeof(int)*2);
  4165.   macrosize=2;
  4166.   macrox=0;
  4167.   macro[macrox++]=1;
  4168.   macro[macrox++]=(int)strdupp(buf+x);
  4169.   buf[q]=macroc;
  4170.   if(macroc=='\"') x=q+1;
  4171.   else x=q;
  4172.   }
  4173.  else
  4174.   {
  4175.   macroc=buf[x];
  4176.   buf[x]=0;
  4177.   for(y=0;y!=context->size;y++)
  4178.     if(!strcmp(context->cmd[y].name,buf)) goto foundit;
  4179.   printf("Key function not found %s\n",buf);
  4180.   continue;
  4181.   foundit:
  4182.  
  4183.   macro=(int *)malloc(sizeof(int)*2);
  4184.   macro[0]=0;
  4185.   macro[1]=y;
  4186.   macrox=2;
  4187.   macrosize=2;
  4188.   buf[x]=macroc;
  4189.   }
  4190.  
  4191.  fn:
  4192.  if(buf[x]==',')
  4193.   if(buf[++x]=='\"')
  4194.    {
  4195.    int q;
  4196.    for(q= ++x;buf[q];++q)
  4197.     if(buf[q]=='\"' && buf[q-1]!='\\' || buf[q]=='\n') break;
  4198.    macroc=buf[q]; buf[q]=0;
  4199.    if(macrox==macrosize) macro=(int *)realloc(macro,sizeof(int)*(macrosize+=2));
  4200.    macro[macrox++]=1;
  4201.    macro[macrox++]=(int)strdupp(buf+x);
  4202.    buf[q]=macroc;
  4203.    if(macroc=='\"') x=q+1;
  4204.    else x=q;
  4205.    goto fn;
  4206.    }
  4207.   else
  4208.    {
  4209.    int q;
  4210.    for(q=x;buf[q];++q) if(buf[q]=='\t' || buf[q]==' ' || buf[q]==',') break;
  4211.    macroc=buf[q]; buf[q]=0;
  4212.    for(y=0;y!=context->size;++y)
  4213.     if(!strcmp(context->cmd[y].name,buf+x)) goto ff;
  4214.    printf("Key function not found %s\n",buf+x);
  4215.    free(macro);
  4216.    continue;
  4217.    ff:
  4218.    if(macrox==macrosize) macro=(int *)realloc(macro,sizeof(int)*(macrosize+=2));
  4219.    macro[macrox++]=0;
  4220.    macro[macrox++]=y;
  4221.    buf[q]=macroc; x=q;
  4222.    goto fn;
  4223.    }
  4224.  
  4225.  if(macrox==macrosize) macro=(int *)realloc(macro,sizeof(int)*(++macrosize));
  4226.  macro[macrox]= -1;
  4227.  
  4228.  kmap=0;
  4229.  n= -1;
  4230.  for(;buf[x];x++) if(buf[x]!=' ' && buf[x]!='\t') break;
  4231.  while(1)
  4232.   {
  4233.   int c;
  4234.   if(buf[x]==' ') x++;
  4235.   if(!buf[x]) break;
  4236.   if(buf[x]=='\n' || buf[x]==' ' || buf[x]=='\t') break;
  4237.   /* Got Next key */
  4238.   x++;
  4239.   if(buf[x-1]=='^')
  4240.    if(buf[x]==' ' || buf[x]=='\t' || buf[x]=='\n' || !buf[x]) c='^';
  4241.    else if(buf[x]=='?') c=127, x++;
  4242.    else c=(buf[x]&0x1f), x++;
  4243.   else if((buf[x-1]&0x5f)=='S' && (buf[x]&0x5f)=='P') c=' ', x++;
  4244.   else c=buf[x-1];
  4245.   /* Add it as if it were a submap */
  4246.   if(!kmap)
  4247.    {
  4248.    if(!(kmap=context->kmap))
  4249.     {
  4250.     kmap=(KMAP *)malloc(sizeof(KMAP));
  4251.     kmap->keys=(KEY *)malloc(4*sizeof(KEY));
  4252.     kmap->size=4;
  4253.     kmap->len=0;
  4254.     context->kmap=kmap;
  4255.     }
  4256.    }
  4257.   else
  4258.    if(kmap->keys[n].k&KEYSUB) kmap=(KMAP *)(kmap->keys[n].n);
  4259.    else
  4260.     {
  4261.     kmap->keys[n].n=(int *)malloc(sizeof(KMAP));
  4262.     kmap->keys[n].k|=KEYSUB;
  4263.     kmap=(KMAP *)(kmap->keys[n].n);
  4264.     kmap->keys=(KEY *)malloc(4*sizeof(KEY));
  4265.     kmap->len=0;
  4266.     kmap->size=4;
  4267.     }
  4268.   for(n=0;n!=kmap->len;n++)
  4269.    if((kmap->keys[n].k&KEYMASK)==c) goto sub;
  4270.    else if((kmap->keys[n].k&KEYMASK)>c) break;
  4271.   if(kmap->len==kmap->size)
  4272.    kmap->keys=(KEY *)realloc(kmap->keys,sizeof(KEY)*(kmap->size+=8));
  4273.   for(z=kmap->len;z!=n;z--) kmap->keys[z]=kmap->keys[z-1];
  4274.   kmap->len++;
  4275.   kmap->keys[n].k=c;
  4276.   kmap->keys[n].n=macro;
  4277.   sub:;
  4278.   }
  4279.  }
  4280. fclose(fd);
  4281. printf("done\n");
  4282. return 0;
  4283. }
  4284.  
  4285. int main(argc,argv)
  4286. unsigned char *argv[];
  4287. {
  4288. if(process(KEYMAP,&km))
  4289.  {
  4290.  unsigned char *hh=(unsigned char *)getenv("HOME");
  4291.  if(!hh) goto in;
  4292.  strcpy(gfnam,hh);
  4293.  strcat(gfnam,"/");
  4294.  strcat(gfnam,KEYMAP);
  4295.  if(process(gfnam,&km))
  4296.   {
  4297.   in:
  4298.   if(process(KEYDEF,&km))
  4299.    {
  4300.    printf("Couldn't open keymap\n");
  4301.    return 1;
  4302.    }
  4303.   }
  4304.  }
  4305. curmap=km.kmap;
  4306. if(argc>2)
  4307.  {
  4308.  fputs("\nIllegal number of command line arguments",stderr);
  4309.  fputs("\nEditor Command Format:  joe [filename]\n",stderr);
  4310.  return 0;
  4311.  }
  4312. termtype();
  4313. curwin=(struct window *)malloc(sizeof(struct window));
  4314. topwin=curwin;
  4315. curwin->next=curwin;
  4316. curwin->prev=curwin;
  4317. markbuf=0;
  4318. curwin->height=height;
  4319. curwin->wind=0;
  4320. curwin->buffer=(struct buffer *)malloc(sizeof(struct buffer));
  4321. curbuf=curwin->buffer;
  4322. curbuf->count=1;
  4323. sigjoe();
  4324. aopen();
  4325. dopen();
  4326. fmopen();
  4327. bof();
  4328. options=0;
  4329. sstring[0]=0;
  4330. rstring[0]=0;
  4331. leave=0;
  4332.  
  4333. rmargin=width-4;
  4334. tabmagic=0;
  4335. wrap=1;
  4336. autoind=0;
  4337. overwrite=0;
  4338. pic=0;
  4339. stmode("");
  4340.  
  4341. gfnam[0]=0;
  4342.  
  4343. if(argc==2)
  4344.  {
  4345.  strcpy(gfnam,argv[1]);
  4346.  stmode(gfnam);
  4347.  handle=fopen(argv[1],"r");
  4348.  if(handle)
  4349.   {
  4350.   if(!fminsfil(handle))
  4351.    omsg=(unsigned char *)"\\iError reading file\\i";
  4352.   else
  4353.    changed=0;
  4354.   fclose(handle);
  4355.   }
  4356.  else
  4357.   {
  4358.   if(errno==ENOENT)
  4359.    {
  4360.    omsg=(unsigned char *)"New File";
  4361.    backup=1;
  4362.    }
  4363.   else
  4364.    omsg=(unsigned char *)"\\iError opening file\\i";
  4365.   }
  4366.  }
  4367. else omsg=(unsigned char *)"New File";
  4368. edit();
  4369. aclose();
  4370. signorm();
  4371. return 0;
  4372. }
  4373.  
  4374. tsignal(sig)
  4375. {
  4376. unsigned char nam[PATHSIZE];
  4377. long tim=time(0);
  4378. struct window *orig=curwin;
  4379. sprintf(nam,"%s%d",ABORT,getpid());
  4380. handle=fopen(nam,"a");
  4381. fmpoint(0);
  4382. fprintf(handle,"\n*** Files in JOE when it aborted on %s",ctime(&tim));
  4383. if(sig) fprintf(handle,"*** JOE was aborted by the signal %d\n",sig);
  4384. else fprintf(handle,"*** JOE was aborted because stdin closed\n");
  4385. if(gfnam[0]) fprintf(handle,"*** FILE: %s\n",gfnam);
  4386. else fprintf(handle,"*** FILE: (Unnamed)\n");
  4387. fmsave(handle,fmsize());
  4388. fflush(handle);
  4389. curbuf->count=0;
  4390. do
  4391.  {
  4392.  stwin(curwin);
  4393.  curwin=curwin->next;
  4394.  ldwin(curwin);
  4395.  if(curbuf->count)
  4396.   {
  4397.   fmpoint(0);
  4398.   if(gfnam[0]) fprintf(handle,"*** FILE: %s\n",gfnam);
  4399.   else fprintf(handle,"*** FILE: (Unnamed)\n");
  4400.   fmsave(handle,fmsize());
  4401.   fflush(handle);
  4402.   curbuf->count=0;
  4403.   }
  4404.  }
  4405.  while(curwin!=orig);
  4406. fclose(handle);
  4407. _exit(1);
  4408. }
  4409.